This is my own implementation of Boyer-Moore-Horspool string search algorithm for object pascal. Though tested only in Freepascal / Lazarus, I think the code can also apply to Delphi.
The license of this code is modified LGPL Lazarus adopted(LGPL+permitting static link), so enjoy using it,
Quick instructions:
- Make a TPosBMH object
- Use TPosBMH.PosBMH() to find out the first occurrence
- Use TPosBMH.PosBMHNext() to locate the next occurrence
- If there’s no more, TPosBMH returns Nil
{
Unit PosBMH: Implementation of Boyer-Moor-Horpspool string search algorithm, optimized for consecutive searches
Create a TPosBMH object, use PosBMH() for initializing search, and PosBMHNext() for consecutive search. The return value is always PChar.
Can be used freely under the same license of LCL(Lazarus Component Library), which adopts modified LGPL.
(LGPL + allowing exception for static linking)
©Copyright 2012~2013 Robert Teminian(Hyunse Oh)
}
unit PosBMH;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
type
TPosBMH = class(TObject)
private
FBMHLast: PChar;
FSubString: String;
FSubStringLength: SizeInt;
FBMHSkipTable: Array[0..255] of SizeInt;
procedure FBuildSkipTable();
procedure FPosBMH();
protected
BMHCursor: PChar;
public
function PosBMH(Needle: String; StartAt: PChar; EndAt: PChar): PChar;
function PosBMH(Needle: String; var Haystack: String): PChar;
function PosBMHNext: PChar;
end;
implementation
procedure TPosBMH.FBuildSkipTable();
var
i: Integer;
begin
for i:=0 to 255 do FBMHSkipTable[i]:=FSubStringLength;
for i:=1 to FSubStringLength do FBMHSkipTable[Byte(FSubString[i])]:=FSubStringLength-i;
end;
procedure TPosBMH.FPosBMH();
begin
while BMHCursor if FBMHSkipTable[Byte(BMHCursor^)]=0 then begin
Dec(BMHCursor, FSubStringLength-1);
if CompareByte(BMHCursor^, FSubString[1], FSubStringLength)=0 then Exit
else Inc(BMHCursor, FSubStringLength);
end else Inc(BMHCursor, FBMHSkipTable[Byte(BMHCursor^)]);
end;
BMHCursor:=nil;
end;
function TPosBMH.PosBMH(Needle: String; StartAt: PChar; EndAt: PChar): PChar;
begin
FSubString:=Needle;
FSubStringLength:=Length(FSubString);
BMHCursor:=StartAt;
FBMHLast:=EndAt;
FBuildSkipTable();
FPosBMH();
Result:=BMHCursor;
end;
function TPosBMH.PosBMH(Needle: String; var Haystack: String): PChar;
begin
Result:=PosBMH(Needle, @Haystack[1], @Haystack[Length(Haystack)]);
end;
function TPosBMH.PosBMHNext: PChar;
begin
if(BMHCursorNil) then begin
Inc(BMHCursor, FSubStringLength);
FPosBMH();
end;
Result:=BMHCursor;
end;
end.
No comments:
Post a Comment