#1
|
|||||
|
|||||
PASCAL - Wild Char Pattern Search for Search & Patch Activation
PASCAL SOURCE CODE USED IN INNO SETUP FOR : countryboy's SEARCH & PATCH ACTIVATION
FORUM STRIPS SPACES FROM POST : HERE IS AN EASIER TO UNDERSTAND IMAGE : THE IMAGE WAS BEFORE BUG FIX & CODE CHANGED TO : ( WHILE i <= (BytesRead - Str2FindLen) DO ) -------------------------------------------------------------------------- // Function GetHexFilePos(PatchNumber, Occurance: Integer; File2Search, FindThis, Pattern: String): Longint; // Search File2Search for Occurance of Pattern containing Wild Char, and FindThis to get FindThis Position. // PatchNumber is displayed in Progress Window. Occurance is desired Count of Pattern wanted. // ?? is Wild Char used in HexCode Pattern, but Not 1st, or Last Char ... FindThis can't contain Wild Char // String Function POS is used to find longest part of Pattern containing NO WILD CHAR in the Buffer Read. // If not found then Next Buffer is Read with an overlap := Length of NO WILD STRING - 1 := missed it by 1. // If NoWild found OK, but Pattern End in Next Buffer then Buffer Position moved forward to Pattern Start. // If NoWild found OK, but Pattern Start in Previous Buffer then Buffer Pos moved back to Pattern Start. // If 1st, Mid, & Last Char of Pattern match then LOOP to check if all Char of Pattern Found, and move on. // If Desired Pattern Occurance Found then Flag is Set. If FindThis in Pattern then File Position is Returned. Function GetHexFilePos(PatchNumber, Occurrence : Integer; File2Search: String; FindThis: String; Pattern: String): Longint; VAR Sfile : TFileStream; Buffer : Ansistring; File2Patch, Str2Find, NoWildStr, FindThisStr, PatchNumStr, FileMsg : String; Char1, MidChar, EndChar : Char; BufSize, BytesRead, BufStartPos, NoWildPos, ThisPos, Str2FindLen, NoWild2Start, NoWild2End, MidPos, NextPattern, i, j, k : Longint; PatternFlag : Boolean; ProgressPage : TOutputProgressWizardPage; BEGIN If (Pattern = '') Then Str2Find := HexStr2ByteStr(FindThis) // IF PATTERN NOT PROVIDED: USE FindThis Else Str2Find := HexStr2ByteStr(Pattern); // ELSE CONVERT PATTERN TO BINARY WITH ??? FindThisStr := HexStr2ByteStr(FindThis); // CONVERT FindThis TO BINARY STRING While Str2Find[1] = '?' Do Delete(Str2Find, 1, 1); // DELETE ? FROM START OF PATTERN STRING While Str2Find[Length(Str2Find)] = '?' Do Delete(Str2Find,Length(Str2Find),1); // DELETE ? FROM END LENGTH OF PATTERN STRING Str2FindLen := Length(Str2Find); // GET LENGTH OF PATTERN STRING TO SEARCH FOR If Str2FindLen >= 2 Then MidPos := Str2FindLen Div 2 Else MidPos :=1; // GET MIDDLE OF Pattern IF MORE THAN 2 CHAR While (MidPos < Str2FindLen) And (Str2Find[MidPos] = '?') Do // FIND A MIDDLE CHAR THAT IS NOT = ? MidPos := MidPos + 1; // CONTINUE UNTILL NOT WILDCHAR := '?' MidChar := Str2Find[MidPos]; // GET THE MIDDEL CHAR OF PATTERN : Str2Find EndChar := Str2Find[Str2FindLen]; // GET LAST CHAR OF PATTERN : NO ? Char1 := Str2Find[1]; // GET 1ST CHAR IN PATTERN STRING : NO ? NoWildStr := GetLongestNoWildStr(Str2Find); // LONGEST STRING IN PATTERN WITH NO WILDCHAR : = ? NoWild2Start := Pos(NoWildStr, Str2Find)-1; // COUNT TO SUBSTRACT FROM NoWildPos TO FIND START POS NoWild2End := (Str2FindLen - NoWild2Start)-1; // COUNT TO ADD TO NoWildPos TO FIND END POSSITION PatternFlag := False; // SET FLAG : FOUND DESIRED OCCURANCE OF PATTERN NextPattern := 0; // OCCURANCE FOUND COUNT OF PATTERN Result := 0; // FUNCTION RETURN : This FILE POSITION := 0 NOT FOUND If ShowSearchFileName Then File2Patch := ExtractFileName(File2Search) // SHOW FileName IN PROGRESS WINDOW IF VARIABLE SET Else File2Patch := ''; FileMsg := expandconstant('{cm:Searching}' +' '+ '{cm:File}' ) + // SHOW SEARCHING FILE + File2Patch Format(' : %.2d ... ',[FilesSearched +1])+ File2Patch; // GLOBAL 0 BASED INCREMENTED AFTER SEARCH If PatchNumber <> 0 Then PatchNumStr := expandconstant( // SHOW CUSTOM LANGUAGE PATCH NUMBER IN PROGRESS WINDOW '{cm:Patch}' +' '+ '{cm:number}'+ Format(' : %.2d ... ',[PatchNumber])) else PatchNumStr := ''; Try Sfile := TFileStream.Create(File2Search, FmOpenRead Or FmShareDenyNone); // CREATE FILE OBJECT, AND OPEN FILE : File2Search BufSize := 31744; // BUFFER SIZE: MAX Integer SIZE := 32768 - 1024 SetLength(Buffer, BufSize); // SET BUFFER SIZE - GET MEMORY Try ProgressPage := CreateOutputProgressPage(expandconstant('{cm:Patching}' + // CREATE PROGRESS PAGE CUSTOM LANGUAGE MESSAGE ' '+ '{cm:Program}'+' : ') + aName, expandconstant('{cm:Searching}'+' ...')); ProgressPage.Hide; ProgressPage.SetText(FileMsg, PatchNumStr); ProgressPage.Show; WHILE (Sfile.Position < (Sfile.Size - Str2FindLen)) Do // SEARCH TO FILE END - LENGTH OF PATTERN BEGIN BufStartPos := Sfile.Position; // SAVE BUFFER START: CURRENT - File Position BytesRead := Sfile.Read(Buffer,BufSize); // FILL BUFFER, AND GET COUNT OF BYTES READ ProgressPage.SetProgress(Sfile.Position, Sfile.Size - Str2FindLen); // SHOW PROGRESS If BytesRead < Str2FindLen Then Break; // NOT ENOUGH BYTES READ FOR PATTERN LENGTH NoWildPos := Pos(NoWildStr, Buffer); // USE STRING POSITION FUNCTION TO FIND NoWildStr If (NoWildPos > 0) Then // FOUND NoWild PART OF PATTERN IN THIS BUFFER BEGIN If (NoWild2Start > NoWildPos) OR // PATTERN START IN PREVIOUS BUFFER OR (NoWildPos + NoWild2End > BytesRead) Then // PATTERN END IN NEXT BUFFER Begin If NoWild2Start > NoWildPos then // PATTERN START IN LAST BUFFER NoWildPos - NoWild2Start Sfile.Position := BufStartPos - NoWild2Start; // SET BUFFER START POSITION BACK - NoWild2Start If NoWildPos + NoWild2End > BytesRead Then // PATTERN END NOT IN THIS BUFFER Sfile.Position := (BufStartPos + NoWildPos) - Str2FindLen; // MOVE BUFFER START FORWARD TO POS BEFORE Str2Find Start BufStartPos := Sfile.Position; // SAVE BUFFER START: File Position BytesRead := Sfile.Read(Buffer,BufSize); // REREAD BUFFER - GET COUNT OF BYTES READ NoWildPos := Pos(NoWildStr, Buffer); // GET POSITION OF NoWildStr IN BUFFER End; i := NoWildPos - NoWild2Start; // i := START OF 1ST CHAR IN PATTERN STRING WHILE i <= (BytesRead - Str2FindLen) DO // WHILE LOOP ( CARRY OVER FROM OLD SEARCH ENGINE ) BEGIN // i SHOULD = 1ST CHAR ( NoWildPos - NoWild2Start ) PatternFlag := false; // NOT found YET ! If (Buffer[i] = Char1) And (Buffer[i+MidPos-1] = MidChar) And // IS 1st CHAR, AND MIDDLE CHAR OF PATTERN IN BUFFER (Buffer[i + Str2FindLen-1] = EndChar) Then // NOW CHECK IF LAST CHAR OF Pattern FOUND. BEGIN // OK, NOW CHECK IF ALL CHAR ARE IN BUFFER j := i; // START AT 1st CHAR OF Str2Find For k := 1 to Str2FindLen Do // CHECK IF ALL CHAR OF Str2Find IN BUFFER Begin if (Buffer[j] <> Str2Find[k]) then // IF NOT FOUND : if (Str2Find[k] <> '?') then Break; // CHECK IF WILDCHAR, OR BREAK k LOOP IF NOT ? j := j + 1 // CONTINUE : CHECK NEXT CHAR IN BUFFER. End; // END OF k LOOP. If k > Str2FindLen then // FOUND IT: STAYED IN k LOOP TO END OF STRING. Begin // FIND DESIRED OCCURANCE OF PATTERN. NextPattern := NextPattern + 1; // INCREMENT THE FOUND COUNT. If (NextPattern >= Occurrence) then // IF DESIRED OCCURANCE FOUND Then SET FLAG, and BREAK. Begin PatternFlag := true; // FOUND : The WHOLE STRING Str2Find IN Buffer Break; // FOUND: BREAK i LOOP : Str2Find IN BUFFER End; // END : If (NextPattern >= Occurrence) End; // END : If k > Str2FindLen END; // END: IF (Buffer[i] = Str2Find[1]) i := i + 1; // CONTINUE NEXT BUFFER CHAR END; // END: ( while i <= BytesRead ) END ELSE i := BufSize - length(NoWildStr); // END If (NoWildPos > 0) OVERLAP NEXT BUFFER READ Sfile.Position := (BufStartPos + (i-1)); // ADD BYTES SEARCHED in Buffer TO FILE POSITION 1 based ProgressPage.SetProgress(Sfile.Position, Sfile.Size); // SHOW PROGRESS If PatternFlag Then // FOUND: Str2Find PATTERN OCCURANCE IN BUFFER Begin BytesRead := Sfile.Read(Buffer,Str2FindLen); // READ Str2Find IN BUFFER, and get count of bytes read ThisPos := (Pos(FindThisStr, Buffer)); // ThisPos := POSITION OF FindThis IN BUFFER PATTERN If ThisPos > 0 Then // IF FindThis FOUND IN PATTERN IN BUFFER Begin ThisPos := ThisPos - 1 // Change 1 base to 0 Based File Postition Result := (BufStartPos + i-1 + ThisPos); // RETURN FILE OFFSET OF THIS End Else Result := 0; // SET NOT FOUND IF FindThis NOT FOUND Break; // BREAK WHILE (Sfile.Position < ) LOOP FOUND Str2Find End Else Result := 0; // SET NOT FOUND IF NO PATTERN FLAG If BytesRead < Str2FindLen Then Break; // ERROR: Fixed - Last Buffer break out: END; // END OF WHILE (Sfile.Position < ) LOOP If Result <> 0 Then ProgressPage.SetText(FileMsg, PatchNumStr + FoundMsg) // CODE FOUND: CUSTOM LANGUAGE TRANSLATION MESSAGE Else ProgressPage.SetText(FileMsg, PatchNumStr + NotFoundMsg); // SHOW CUSTOM LANGUAGE TRANSLATION NOT FOUND MESSAGE Sleep(SearchMsgWaitTime); // GLOBAL WAIT TIME IN MILISECONDS TO VIEW FOUND MESSAGE Finally Sfile.Free end; // FREE FILE OBJECT's MEMORY ON HEAP SetLength(Buffer, 0); // FREE BUFFER MEMORY Finally ProgressPage.Hide; end; // HIDE THE PROGRESS PAGE END; Just fixed a bug where a very long search Pattern missed the last byte : Quote:
70 Files - 320 Patches : Search Time := 39 Seconds Code:
PATTERNS USED IN : Toon Boom_Harmony 20.0.3.16743 Activation Search & Patch ACTIVATION :https://mir.cr/JOMBDHA0 Harmony Premium 20.0.3.16743 SETUP 59 Files - 196 Patches ... 01 Minutes, 46 Seconds Code:
PATTERNS USED IN : Toonboom Harmony Premium 21.0.0.17367 Activation ACTIVATION : https://mir.cr/AXV5GY4L Toonboom Harmony Premium 21.0.0.17367 SETUP THE SEARCH PATTERN WAS IN 24 FILES The 1 BYTE TOO LONG : Bug was fixed after the Release ! If anyone sees a possible bug, or has any ideas on CODE IMPROVEMENT FOR A FASTER PATTERN SEARCH THEN I'am Interested. Have a great day, countryboy *************************************************************************************************************************** SUPPORT FUNCTIONS CALLED BY PATTERN SEARCH ENGINE .. Quote:
Quote:
ORIGINAL : WHILE i < (BytesRead - Str2FindLen) DO // WHILE LOOP ( CARRY OVER FROM OLD SEARCH ENGINE ) CHANGED : WHILE i <= (BytesRead - Str2FindLen) DO // WHILE LOOP ( CARRY OVER FROM OLD SEARCH ENGINE ) REASON . : BUG : MISSED PATTERN - IF PATTERN WAS 1 BYTE TO LONG. ORIGINAL : Sfile.Position := (BufStartPos + NoWildPos) - Str2FindLen; // MOVE BUFFER START FORWARD TO POS BEFORE Str2Find Start CHANGED : Sfile.Position := (BufStartPos + NoWildPos) - NoWild2Start; // MOVE BUFFER START FORWARD TO POS OF Str2Find Start REASON . : MOVED BUFFER TO START OF Str2Find : not before, but exact position DIFFERENCE IS ( Str2FindLen = NoWildPos ) bytes moved ahead. Have a great day, countryboy Last edited by countryboy; 09-21-2021 at 07:32. |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Search Not working | davo007 | General Discussion | 2 | 07-20-2009 07:27 |