home *** CD-ROM | disk | FTP | other *** search
- {*****************************************************************
- * A demonstration of how to create and read "memory image" text *
- * files to get faster file loading. *
- * (C) Daniel A. Bronstein, Michigan State University, 1991. *
- * May be freely used and modified provided attribution is made.*
- *****************************************************************}
- program fastload;
- uses
- crt,ptrmath;
-
- type
- buffer = array[1..1] of char;
- buffptr = ^buffer;
- strptr = ^string;
- sparray = array[1..1] of strptr;
- sparrptr = ^sparray;
- str12 = string[12];
-
- var
- sa : sparrptr;
-
- {******************************************************************
- * MakeFLF - make a "memory image" fast loading file (fn2) from an *
- * ASCII text file (fn1), substituting ts spaces for all tabs. *
- ******************************************************************}
- procedure makeFLF(fn1,fn2:string;ts:word);
- const
- zip : char = #0;
- var
- inf : text;
- outf : file of char;
- s : string;
- tabstr : string[8]; {Arbitrary tab size limit.}
- c,l : word;
- begin
- {$I-}
- assign(inf,fn1); {Open the files.}
- reset(inf);
- if ioresult <> 0 then halt(1);
- assign(outf,fn2);
- rewrite(outf);
- if ioresult <> 0 then halt(1);
- {$I+}
- if ts > 8 then ts := 8; {Create a string to replace tab}
- tabstr[0] := chr(ts); {characters (#9).}
- fillchar(tabstr[1],ts,' ');
- {Save space at start of file for line count:}
- for c := 1 to sizeof(word) do write(outf,zip);
- l := 0;
- while not eof(inf) do
- begin
- readln(inf,s); inc(l); {Read line and inc line count,}
- c := pos(#9,s); {then replace tabs with spaces.}
- while c <> 0 do
- begin
- delete(s,c,1);
- insert(tabstr,s,c);
- c := pos(#9,s);
- end; {Write string (including length byte)}
- for c := 0 to ord(s[0]) do write(outf,s[c]); {to FLF file.}
- end;
- close(inf);
- seek(outf,0); {Go back to begining of file}
- zip := chr(lo(l)); write(outf,zip); {and write the line count.}
- zip := chr(hi(l)); write(outf,zip);
- close(outf);
- end;
-
- {*******************************************************************
- * ReadFLF - read the "memory image" fast loading file (fn) into an *
- * array of pointers. *
- *******************************************************************}
- {If you might have more than 32,767 lines, make this a longint:}
- function readFLF(fn:str12):integer;
- var
- cf : file;
- sp : strptr;
- bp : buffptr;
- sz,fl,l,c,totc : word;
- ovflow,fpos,ccnt : longint;
- begin
- {$I-}
- assign(cf,fn); {Open the FLF file.}
- reset(cf,1);
- {$I+}
- if ioresult <> 0 then halt(1);
- ovflow := filesize(cf)-2; {Save filesize less line count}
- blockread(cf,fl,2); {and get the line count (fl).}
- if fl > 16380 then fl := 16380; {Largest array space is 1 segment.}
- getmem(sa,fl*sizeof(strptr)); {Get enough memory for fl pointers.}
- l := 0; {Init lines created & file position.}
- fpos := 3; {Let's be sure to leave some memory}
- if maxavail > $100 then {for other uses after partial read.}
-
- REPEAT {*** Loop start ***}
- {If filesize > largest allocable block..}
- if ovflow > $FFF0 then sz := $FFF0
- else sz := ovflow; {..use largest allocable.}
- if maxavail < sz then {If not enough memory for full read}
- sz := maxavail - $100; {leave some memory for other uses.}
- ovflow := ovflow - sz; {Determine amount left in file.}
- ccnt := 0; {Initialize character counter.}
- getmem(bp,sz); {Allocate memory for contents,}
- bp := baseptr(bp); {make sure is in XXXX:000X form,}
- sp := strptr(bp); {and initialize the string pointer.}
- blockread(cf,bp^,sz,totc); {BLOCKREAD; totc has actual count.}
-
- {While lines and chars remain: }
- while (l < fl) and (ccnt < totc) do
- begin {inc line count, assign strptr to}
- inc(l); sa^[l] := sp; {array, get length of the string}
- c := succ(ord(sp^[0])); {inc it and add it to strptr to}
- sp := ptrinc(sp,c); {get next line location and to}
- ccnt := ccnt + c; {the character counter.}
- end;
- if ovflow > 0 then {If not at EOF,}
- begin
- fpos := fpos + ccnt; {get new file position.}
- if ccnt > totc then {If didn't read whole of last line,}
- begin {abandon the last array pointer}
- dec(l); {by dec'ing(l), }
- fpos := fpos - c; {calculate new file start position}
- ovflow := ovflow + c; {and size, and}
- seek(cf,fpos); {set file there, then loop back.}
- end;
- end;
- UNTIL (l >= fl) or (maxavail <= $100); {*** Loop end. ***}
- close(cf);
- if l < fl then readFLF := -l else {If only partial read, return a}
- readFLF := l; {negative line count, else positive.}
- end;
-
- {*****************************************************************
- * ShowFLF - simple-minded, forward only, screen-at-a-time array *
- * viewer showing l lines. *
- *****************************************************************}
- procedure showFLF(l:word);
- var
- a : word;
- k : char;
- begin
- a := 1;
- repeat
- clrscr;
- for a := a to a + 23 do
- begin
- if a > l then exit else writeln(sa^[a]^);
- end;
- if a > l then exit else
- write('Q to Quit, any other key for more');
- k := upcase(readkey);
- until (a >= l) or (k = 'Q');
- end;
-
- {*************************
- * FASTLOAD main program. *
- *************************}
- var
- fn,fn1 : string[12];
- a,b : integer;
- begin
- fn := paramstr(1); {First param is file name, second}
- if paramcount < 2 then a := 5 else {is tabsize (default = 5).}
- begin
- fn1 := paramstr(2);
- for a := 1 to ord(fn1[0]) do
- if not (fn1[a] in ['0'..'9']) then delete(fn1,a,1);
- val(fn1,a,b);
- if b <> 0 then a := 5;
- end;
- fn1 := fn;
- if pos('.',fn1) <> 0 then {Create FLF filename.}
- begin
- while fn1[ord(fn1[0])] <> '.' do dec(fn1[0]);
- fn1 := fn1 + 'flf';
- end else fn1 := fn1 + '.flf';
- makeFLF(fn,fn1,a); {Make the FLF file,}
- writeln(fn,' read and ',fn1,' created.');
- a := readFLF(fn1); {read the FLF file}
- showFLF(abs(a)); {and display it.}
- end.