FIX: Viewer - Slow case insensitive backward search with single byte encoding

(cherry picked from commit cb9b79a26d)
This commit is contained in:
Alexander Koblov 2023-01-27 21:26:10 +03:00
commit b0ca10d89b
2 changed files with 77 additions and 1 deletions

View file

@ -2521,7 +2521,7 @@ begin
if bTextFound then FLastSearchPos := PAnsiAddr - ViewerControl.GetDataAdr;
end
// Using very slow search algorithm
else if (ViewerControl.Encoding in ViewerEncodingMultiByte) or bSearchBackwards then
else if (ViewerControl.Encoding in [veUtf32le, veUtf32be]) then
begin
PAdr := ViewerControl.FindUtf8Text(FLastSearchPos, sSearchTextU,
FFindDialog.cbCaseSens.Checked,
@ -2529,6 +2529,16 @@ begin
bTextFound := (PAdr <> PtrInt(-1));
if bTextFound then FLastSearchPos := PAdr;
end
// Using special case insensitive single byte encoding search algorithm
else if bSearchBackwards then
begin
RecodeTable:= InitRecodeTable(ViewerControl.EncodingName, FFindDialog.cbCaseSens.Checked);
PAnsiAddr := PosMemA(ViewerControl.GetDataAdr, ViewerControl.FileSize,
FLastSearchPos, sSearchTextA,
FFindDialog.cbCaseSens.Checked, bSearchBackwards, RecodeTable);
bTextFound := (PAnsiAddr <> Pointer(-1));
if bTextFound then FLastSearchPos := PAnsiAddr - ViewerControl.GetDataAdr;
end
// Using very fast BoyerMoore search algorithm
else begin
RecodeTable:= InitRecodeTable(ViewerControl.EncodingName, FFindDialog.cbCaseSens.Checked);

View file

@ -18,6 +18,9 @@ unit uFindMmap;
interface
uses
uFindByrMr;
type
TAbortFunction = function: Boolean of object;
@ -45,6 +48,10 @@ function PosMemU(pDataAddr: PChar; iDataLength, iStartPos: PtrInt;
function PosMemW(pDataAddr: PChar; iDataLength, iStartPos: PtrInt;
const sSearchText: String; bSearchBackwards, bLittleEndian: Boolean): Pointer;
function PosMemA(pDataAddr: PChar; iDataLength, iStartPos: PtrInt;
const sSearchText: String; bCaseSensitive, bSearchBackwards: Boolean;
RecodeTable: TRecodeTable): Pointer;
{en
Searches a file for a string using memory mapping.
@ -278,6 +285,65 @@ begin
end;
end;
function PosMemA(pDataAddr: PChar; iDataLength, iStartPos: PtrInt;
const sSearchText: String; bCaseSensitive, bSearchBackwards: Boolean;
RecodeTable: TRecodeTable): Pointer;
var
SearchTextLength: Integer;
function sPos2(pAdr: PChar):Boolean; inline;
var
i: Integer;
begin
Result := False;
for i := 1 to SearchTextLength do
begin
case bCaseSensitive of
False: if Chr(RecodeTable[Ord(pAdr^)]) <> Chr(RecodeTable[Ord(sSearchText[i])]) then Exit;
True : if pAdr^ <> sSearchText[i] then Exit;
end;
Inc(pAdr);
end;
Result:=True;
end;
var
pCurrentAddr, pEndAddr: PAnsiChar;
begin
Result := Pointer(-1);
SearchTextLength := Length(sSearchText);
if (SearchTextLength <= 0) or (iDataLength <= 0) then
Exit;
pCurrentAddr := pDataAddr + iStartPos;
pEndAddr := pDataAddr + iDataLength - SearchTextLength;
if bSearchBackwards and (pCurrentAddr > pEndAddr) then
// Move to the first possible position for searching backwards.
pCurrentAddr := pEndAddr;
if (pEndAddr < pDataAddr) or (pCurrentAddr < pDataAddr) or (pCurrentAddr > pEndAddr) then
Exit;
while True do
begin
if (pCurrentAddr > pEndAddr) or (pCurrentAddr < pDataAddr) then
Exit;
if sPos2(pCurrentAddr) then
begin
Result := pCurrentAddr;
Exit;
end;
case bSearchBackwards of
False: Inc(pCurrentAddr);
True : Dec(pCurrentAddr);
end;
end;
end;
function FindMmap(const sFileName: String; const sFindData: String;
bCase: Boolean; Abort: TAbortFunction): Integer;