[Back to TEXTFILE SWAG index] [Back to Main SWAG index] [Original]
{ unit for reading text files up to 512K very quickly! }
{ Do whatever you like to this code, but please credit me somehow! }
{ by Itai Handler, FidoNet 2:406/120. }
Unit FastText;
Interface
const
Text_Eof : Boolean = true;
NoMem : Boolean = false;
Function Text_Load (FN:String):Boolean; { init memory and read the file }
Procedure Text_ReadLine (var S:String); { get line from text }
Procedure Text_GoBack (L:Word); { updates pointer to L lines back }
Function Text_Lines:LongInt; { calculate how many lines in file }
Procedure Text_Reset; { reset file & seek to start }
Procedure Text_Dispose; { free memory }
Implementation
Type
BufType=Array[1..64000] of char;
Const
PUsed:Byte=0; { # of pointers currently in use }
Var
P:Array[1..8] of ^BufType; { array of 8 pointers (512kb) }
TextSize:LongInt; { size of the text file in bytes }
PSeek:LongInt;
PCur:LongInt;
Function Text_Load (FN:String):Boolean; { init memory and read the file }
Var
FB:File of Byte;
NumRead:Word;
F:File;
B:LongInt;
FM:Byte;
Tmp:LongInt;
Begin
FM:=FileMode;
filemode:=64;
Text_Load:=false;
NoMem:=false;
Assign(fb, FN);
Reset(fb);
TextSize:=FileSize(fb);
Close(Fb);
If MaxAvail>=TextSize then
Begin
Text_Load:=true;
For B:=1 to 8 do if TextSize > (( Pred(B) )*64000) then
Begin
If B*64000>TextSize then Tmp:=(TextSize mod 64000) else
Tmp:=64000;
GetMem(P[B],Tmp);
Inc(PUsed);
End;
Assign(f, FN);
Reset(f,1);
For B:=1 to PUsed do
Begin
If B*64000>TextSize then Tmp:=(TextSize mod 64000) else
Tmp:=64000;
BlockRead(F,P[B]^,Tmp,NumRead);
{If NumRead<>Tmp then Text_Load:=false;}
End;
Close(F);
End else NoMem:=true;
FileMode:=FM;
PSeek:=1;
PCur:=1;
Text_Eof:=false;
End;
Procedure Text_ReadLine (var S:String); { get line from text }
Var
W:Word;
B:LongInt;
TS:String;
Tmp:LongInt;
Begin
TS:='';
If Not Text_Eof then
Begin
While (PUsed>=PCur) and (Length(TS)<=255) and
(P[PCur]^[PSeek]<>#13) {and (P[PCur]^[PSeek]<>#10)} do
Begin
TS:=TS+P[PCur]^[PSeek];
Inc(PSeek);
If (PSeek>64000) and (PCur<8) then
Begin
PSeek:=1;
Inc(PCur);
End;
End;
If (P[PCur]^[PSeek]=#13) and (PUsed>=PCur) then
begin
Inc(PSeek,2);
If (PSeek>64000) and (PCur<8) then
Begin
PSeek:=1;
Inc(PCur);
End;
end;
If (PCur>PUsed) or (Pred(PCur)*64000+PSeek>TextSize) then
Text_Eof:=true;
End;
S:=TS;
End;
Procedure Text_GoBack (L:Word);
Var
Cnt : Word;
Begin
Cnt:=L;
If Cnt>0 then
Begin
If PSeek>2 then Dec(PSeek,2) else
If PCur>1 then Begin Dec(PCur); PSeek:=64000-PSeek+1; End;
Repeat
Dec(Cnt);
Repeat
If PSeek>0 then Dec(PSeek);
If (PSeek=0) and (PCur>1) then
Begin
PSeek:=64000;
Dec(PCur);
End;
If PSeek=0 then PSeek:=1;
Until ((PSeek=1) and (PCur=1)) or (P[PCur]^[PSeek]=#13)
Until Cnt=0;
If not ((PSeek=1) and (PCur=1)) Then Inc(PSeek,2);
If PSeek>64000 then PSeek:=PSeek-64000;
End;
Text_Eof:=false;
End;
Function Text_Lines:LongInt;
(* Asm procedure was made by Arie Vayner on the 9/2/95 *)
Var
W:Word;
B:LongInt;
L:Word;
Tmp:Word;
O:Word;
S:Word;
Begin
L:=1;
For B:=1 to PUsed do
Begin
If B*64000>TextSize then Tmp:=(TextSize mod 64000) else
Tmp:=64000;
O:=Ofs(P[B]^);
S:=Seg(P[B]^);
Asm
Push DS
Mov DS,S
XOR DX,DX
MOV CX,TMP
MOV SI,O
CLD
@MAINLOOP:
LODSB
CMP AL,10
JE @FOUND_ONE
LOOP @MAINLOOP
JMP @EXITLOOP
@FOUND_ONE:
INC DX
LOOP @MAINLOOP
@EXITLOOP:
MOV AX,DX
MOV TMP,AX
POP DS
END;
Inc(L,TMP);
End;
Text_Lines:=L;
End;
Procedure Text_Reset; { reset file & seek to start }
Begin
Text_Eof:=false;
PCur:=1;
PSeek:=1;
End;
Procedure Text_Dispose; { free memory }
Var
B:LongInt;
Tmp:LongInt;
Begin
For B:=1 to PUsed do if TextSize > (B*64000) then
Begin
If B*64000>TextSize then Tmp:=(TextSize mod 64000) else
Tmp:=64000;
FreeMem(P[B],Tmp);
End;
PUsed:=0;
End;
End.
[Back to TEXTFILE SWAG index] [Back to Main SWAG index] [Original]