Implementation of Boyer-Moore-Horspool string search algorithm forFreepascal / Lazarus

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:

  1. Make a TPosBMH object
  2. Use TPosBMH.PosBMH() to find out the first occurrence
  3. Use TPosBMH.PosBMHNext() to locate the next occurrence
  4. If there’s no more, TPosBMH returns Nil
Now, here comes the code. Enjoy!

{
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

블로그를 이전합니다

뭐, 이런 작은 변방의 블로그에 관심있으신 분들은 아무도 없으시리라 생각합니다만...... (웃음) 블로그 플랫폼을 블로거에서 dev.to로 옮겼습니다. 새 URL은 아래와 같습니다: https://dev.to/teminian 새로운 거처에서 뵙겠습니...

Popular in Code{nested}