Contributor: CAMERON CLARK { The following 3 messages will include two units [files,freebuff] and one driver program [CTP]. The purpose of CTP is to reformate you source code's case use, Exampe: change 'writeln' to 'WriteLn'. It includes all reserved words. FREEBUFF is where most of the speed increase comes from. It is a free read buffer styled much like blockRead and BlockWrite. It does the job of a disk cache by NOT writing until the write buffer is full, and NOT reading until the read buffer is empty. It can be used for any program in place of blockread&write where small pieces of information need to be extracted. remeber memory is fast, drives are slow. CTP still needs some optimizing [and inclusion of the (* *) comments Words in quotes '' or Comments { WILL be skipped. If you can speed it up, re-post the optimized version. } UNIT FILES; INTERFACE USES DOS; FUNCTION FileExists(FileName: String): Boolean; FUNCTION OpenFile(VAR f: file; fileName:string): Boolean; FUNCTION FileExistsWild(FileName: String): Boolean; IMPLEMENTATION FUNCTION FileExists(FileName: String): Boolean; VAR F: file; begin {$I-} Assign(F, FileName); Reset(F); Close(F); {$I+} FileExists:=(IOResult = 0) and (FileName <> '') end; { FileExists } FUNCTION OpenFile(VAR f: file; fileName:string): Boolean; BEGIN IF fileExists(FileName) then BEGIN Assign(f,filename); Reset(f,1); Openfile:=True; END ELSE OpenFile:=False; END; FUNCTION FileExistsWild(FileName: String): Boolean; VAR Fil: SearchRec; begin FindFirst(FileName,anyFile,Fil); FileExistsWild:=(DosError=0) and (FileName <> ''); end; { FileExists } BEGIN END. {UNIT FREEBUFF} {12/7/94} {v4.0 ... Changing into a unit } Unit FreeBuff; INTERFACE VAR TrueFileEnd : Boolean; PROCEDURE B_Read( var F: file; var userObject; ObjSize: Word; VAR bytesREAD: Word); PROCEDURE B_Write( var FW: file; var userObject; ObjSize: Word); PROCEDURE B_Skip( var F: File; SkipSize: Integer); {user may skip any size} PROCEDURE InitBuffers(Var F: File; Var FW : File); PROCEDURE FlushWRITEBuffer(Var FW : File); IMPLEMENTATION CONST rBufSize=8192; {buffer size for B_read} wBufSize=8192; {buffer size for B_write} VAR rBuffer: array [1..rBufSize] of char; {buffer for B_read} rCurrent: word; {8192 < word max} {current position in rBuffer} rEnd: Integer; {Logical end of buffer} FileEnd: Boolean; {Actual file end} wBuffer: array [1..wBufSize] of char; {buffer for B_Write} wCurrent: word; {current position in wBuffer} Function WhatsLeft : Word; BEGIN If rEnd> (rCurrent -1) THEN BEGIN WhatsLeft:= rEnd - (rCurrent - 1); {last position - (Current-1) } END ELSE BEGIN WhatsLeft:=0; END; END; FUNCTION WhatsLeftinWRITE: Word; BEGIN WhatsLeftinWRITE:=wBufSize - (wCurrent - 1); END; PROCEDURE ReadBuffer(Var f: file; Var UserObject; ObjSize: Word; VAR BytesRead: word); BEGIN BLockRead(F,UserObject,ObjSize,BytesRead); rEnd:=(rCurrent-1) + BytesRead; IF (BytesRead <> ObjSize) Then BEGIN FileEnd:=True; END; END; PROCEDURE WriteBuffer(Var FW: File; var UserObject; ObjSize: word); VAR wDummy: Word; BEGIN BlockWrite(FW,UserObject,ObjSize,wDummy); END; PROCEDURE InitReadBuffer(Var F: File); VAR Dummy: Word; BEGIN rCurrent:=1; ReadBuffer(F,rBuffer[1],rBufSize,Dummy); END; PROCEDURE InitWRITEBuffer; BEGIN wCurrent:=1; END; PROCEDURE InitBuffers(Var F: File; Var FW : File); BEGIN FileEnd:=False; TrueFileEnd:=False; InitReadBuffer(F); InitWriteBuffer; END; PROCEDURE FlushWRITEBuffer(Var FW : File); BEGIN WriteBuffer(FW, wBuffer[1], wCurrent-1); initWriteBuffer; END; PROCEDURE B_Read( var F: file; var userObject; ObjSize: Word; VAR bytesREAD:Word); VAR LeftInBuf: Word; Temp: Word; BytesMoved: Word; BEGIN LeftInBuf:= WhatsLeft; IF ObjSize < LeftInBuf then BEGIN {Same case for if FileEnd} {CASE 1 MOST COMMON} Move(rBuffer[rCurrent], UserObject, ObjSize); rCurrent:=rCurrent+ ObjSize; BytesRead:=ObjSize; END ELSE IF ObjSize > LeftInBuf then BEGIN {CASE 2 SECOND MOST COMMON} IF FileEnd then BEGIN LeftInBuf:=WhatsLeft; Move(rBuffer[rCurrent], UserObject, LeftInBuf); BytesRead:=LeftInBuf; TrueFileEnd:=true; END ELSE BEGIN LeftInBuf:=WhatsLeft; BytesMoved:=LeftInBuf; Move(rBuffer[rCurrent], rBuffer[1], LeftInBuf); rCurrent:=LeftInBuf+1; rEnd:= rBufSize; LeftInBuf:=WhatsLeft; ReadBuffer(F, rBuffer[rCurrent], LeftInBuf, BytesRead); IF FIleEnd Then BEGIN BytesRead:=BytesRead+BytesMoved; IF BytesRead < ObjSize THEN BEGIN move(rBuffer[1],UserObject, BytesRead); TrueFileEnd:=True; END ELSE BEGIN move(rBuffer[1],UserObject, ObjSize); rCurrent:=ObjSize+1; BytesRead:=ObjSize; END; END ELSE BEGIN move(rBuffer[1],UserObject, ObjSize); BytesRead:=ObjSize; rCurrent:=ObjSize+1; END; END; END ELSE IF ObjSize = LeftInBuf then BEGIN {CASE 3 MOST UNCOMMON} IF FileEnd then BEGIN move(rBuffer[rCurrent], UserObject, objSize); BytesRead:=ObjSize; TrueFileEnd:=True; END ELSE BEGIN move(rBuffer[rCurrent], UserObject, objSize); InitReadBuffer(f); BytesREad:=ObjSize; END; END; END; PROCEDURE B_Skip( var F: File; SkipSize: Integer); {user may skip any size} var LeftInBuffer :Word; BEGIN LeftInBuffer:= WhatsLeft; IF LeftInBuffer > SkipSize THEN BEGIN Seek(F, FilePos(F) + ( SkipSize - LeftINBuffer)); InitREADBuffer(F); END ELSE BEGIN IF LeftINBuffer = SkipSize THEN BEGIN InitREADBuffer(F); END ELSE BEGIN rCurrent:=rCurrent + SkipSize; END; END; END; PROCEDURE B_Write( var FW: file; var userObject; ObjSize: Word); var LeftINBuffer: Word; BEGIN LeftInBuffer:=WhatsLeftinWRITE; IF ObjSize < LeftInBuffer THEN BEGIN move(UserObject, wBuffer[wCurrent], ObjSize); wCurrent:=wCurrent+ ObjSize; END ELSE BEGIN IF ObjSize=LeftInbuffer THEN BEGIN move(UserObject, wBuffer[wCurrent], ObjSize); wCurrent := wCurrent + ObjSize; FlushWriteBuffer(FW); END ELSE BEGIN FlushWriteBuffer(FW); move(UserObject, wBuffer[wCurrent], ObjSize); wCurrent:=wCurrent+ ObjSize; END; END; END; BEGIN END. {PROGRAM C-TP-format} {SLOWWWWWWWW} {$A+,B-,D+,E-,F-,G-,I-,K-,L-,N-,P-,R+,S-,T-,V-,W-,X+,Y-} {12/07/94 FIXED FreeBuff : and used it as a unit!!!!!!!!!!!!!!!} { Passes Dos's comp test for a 200k file } Uses crt,dos,FREEbuff,FILES; CONST BufSize=8192; ResSize=53;{Words to Reformat} {Edit these to fit personal capital & lowerCase mixture preferences} TYPE rWords = array[1..ResSize] OF String; {Crt,Graph,Graph3,Overlay,Printer,Strings,System,Turbo3,WinAPI,WinCrt WinDOS,WinPrn,WinProcs,WinTypes ...} {BOOCOOS of typing!!} CONST Reserved : rWords =( 'ABSOLUTE','AND','ASM','ARRAY','BEGIN','CASE','CONST','CONSTRUTOR', 'DESTRUCTOR','DIV','DO','DOWNTO','ELSE','END','EXPORTS','FILE','FOR', 'FUNCTION','GOTO','IF','IMPLEMENTATION','IN','INHERITED','INLINE', 'INTERFACE','LABEL','LIBRARY','MOD','NIL','NOT','OBJECT','OF','OR','PACKED', 'PROCEDURE','PROGRAM','RECORD','REPEAT','SET','SHL','SHR','STRING','THEN', 'TO','TYPE','UNIT','UNTIL','USES','VAR','WHILE','WriteLN','WITH','XOR'); VAR F,OUTf : file; tB : array[1..BufSize] of CHAR; {I, J : integer;} Quote : Boolean; {temp boolean use to skip quoted material} Path,Name,Ext : String; {used for opening input file} Look : SearchRec; {used for opening input file} Dummy : String; {Built string to search for} TB1 : Char; {Temp B_READ byte} tb2 : integer; {Counter} BytesRead : Word; {Dummy: not used in logic} INPUTsize, { used to compare final sizes} OUTPUTsize : LongInt; Capitals : rWords; {used to capitalize all reserved words for} {Speed efficient ONLY comparison } PROCEDURE Announce; BEGIN Writeln('C-TP-Format v1.0 coded by şMr. Krinkleş'); Writeln('Property of Clark Enterprizes. Sept 5 1994'); WriteLN; END; PROCEDURE NEEDhelp; BEGIN WriteLN('Usage: CTP [FileName.in] [FileName.out]'); WriteLN('Example: CTP Onefile.pas NewOne.pas'); HALT; END; PROCEDURE INITcapitals; {Make a Capitalized array of reserved word} VAR I,J :integer; BEGIN FOR I:=1 to ResSize DO BEGIN Capitals[I][0]:=Reserved[i][0]; {init lengths} FOR J:=1 to ORD(Reserved[I][0]) {LENGTH} DO Capitals[I][j]:= UPCASE(Reserved[I][J]); END; END; FUNCTION Sfind( Name : string; Dum:String): boolean; VAR k : integer; ch: char; BEGIN IF Name[0] = Dum[0] THEN BEGIN {Size Check :Speed Efficient} FOR k:=1 To ord(Dum[0]) DO BEGIN {CHar by CHar comparison} IF not ( Name[k] = Dum[k] ) Then BEGIN Sfind:=False; {When FIRST FALSE CASE} EXIT; {Speed Efficient} END; END; END ELSE BEGIN SFINd:=FALSE; {Failed Size Check} EXIT; END; SFind:=True; {The Two are the Same} END; FUNCTION SCANandUPdate(Dummy:String) : String; {needs to be changed to boyerMoore type search string tech} VAR J : integer; Dummy2 : string; BEGIN Dummy2[0]:=Dummy[0]; {length} FOR J:=1 to ord(Dummy[0]) DO Dummy2[J]:=UpCase( Dummy[j] ); {Capitalize} FOR j:=1 to ResSize DO BEGIN IF Sfind(Capitals[j], Dummy2) then BEGIN {check with Capitals array} SCANandUpdate:=Reserved[j]; exit; END;{IF} END; SCANandUPdate:=Dummy; {Return original if not found} END; BEGIN {MAIN SKELETION} Announce; IF ParamStr(1)='' then NEEdhelp; IF ParamStr(2)='' then NEEDhelp; IF ParamStr(1)=ParamStr(2) then NEEDhelp; Fsplit(ParamStr(1), Path, name, ext); If path<>'' then path:=path+'\'; {writeln(path,' ',name,' ',ext);} FINDFIRST(ParamStr(1), AnyFile, LOOK); IF dosError<>0 then NeedHelp; IF not OpenFile(F,path+Look.Name) THEN BEGIN WriteLN('Unable to open ',Look.Name,' : Halting.'); HALT; END; INITcapitals; Assign(OUTf,ParamStr(2)); {open and write output} ReWrite(OUTf,1); {NO preExistance check done} WRITeLN('=< C-TP-Formating ',Look.name,' >='); InitBuffers(F,OUTf); {MUST Initialize the READ and WRITE buffers} b_READ(F,TB1,1,BytesREAD); {initialize tb1} REPEAT REPEAT IF (tb1=#39) THEN BEGIN {ignore initial quote} Quote:=FALSE; WHILE (not Quote) and (not TrueFileEnd) do BEGIN b_write(OUTf,tb1,1); {NO need to check for reserved} b_read(f, tb1, 1,BytesREAD); IF tb1=#39 THEN Quote:=Not Quote; END; b_write(OUTf,tb1,1); {write the closing quote} b_read(f, tb1, 1,BytesREAD); {re-init tb1} END else IF ( tb1 ='{') THEN BEGIN WHILE (tb1<> '}') and (not TrueFileEnd) do BEGIN {spit out info until nex comment} b_write(OUTf,tb1,1); {NO need to check for reserved} b_read(f, tb1, 1,BytesREAD); END; b_write(OUTf,tb1,1); {write the closing comment} b_read(f, tb1, 1,BytesREAD); {re-init tb1} END; UNTIL (tb1 <> #39) and (TB1<> '{') or TrueFileEnd; {tb1 might be another Q or C} IF (tb1 in ['A'..'Z','a'..'z']) THEN BEGIN {build String} Dummy:=''; While (tb1 in ['A'..'Z','a'..'z']) and (not TrueFileEnd) DO BEGIN Dummy:=Dummy+tb1; b_READ(f,tb1,1,BytesREAD); END; Dummy:=SCANandUPDATE(DUMMY); {Scan for reserved} { gotoXY(1,25); CLReol; write(Dummy,' '); } b_WRITE(OUTf,DUMMY[1],ord(DUMMY[0])); END ELSE BEGIN b_write(OUTf,tb1,1); b_read(F,tb1,1,BytesREAD); END; {IF} INC(tb2); CASE TB2 of 1 : BEGIN write(#8#8); Write('.');END; 400 : BEGIN write(#8#8);Write('*');END; 700 : BEGIN write(#8#8);Write(#127);END; 1000 : BEGIN write(#8#8);Write(#30);END; 1300 : BEGIN write(#8#8);write(#254);END; 1600 : tb2:=0; END; UNTIL TrueFileEnd; b_WRite(OUTf,TB1,1); {hopefully spit out the last char} FLushWriteBuffer(OUTf); INPUTsize:= FileSize(F); OUTPUTsize:= FileSize(OUTf); Close(OUTf); Close(F); IF INPUTsize <> OUTPUTsize THEN BEGIN write(#8#8); WriteLN('ERROR (1): Finished file sizes do not match.'); END Else BEGIN write(#8#8); Writeln('Done.'); END; END. (* The previous sources are to format the Case of you TP code. It will skip all words within Quotes '' or Comments {}. The two units are FILES and FREEbuff. The FREEbuff unit is my attempt to uses disk cache logic in my programs. The logic is simple: don't read until read buffer empty don't write until write buffer full. To use FREEbuff do the following INITbuffer( INfile, OUTfile) [must be opened] repeat b_read( INfile, buffer[1], sizeOF(buffer), bytesRead); b_write( OUTfile, buffer[1], BytesRead); until TrueFileEnd; FlushWriteBuffer(Outfile); set it all up Flush empties the write buffer before the file is closed. Syntax is very clock to BlockRead&write. BytesRead is the amount of bytes actually moved to the Buffer [or object] Instead of using blockRead for one byte reading, B_Read will fill the buffer with 8192 bytes and then only give the object one byte. This is extremely efficient when you only need small part of a file. *)