首页 > 代码库 > TSearch & TFileSearch Version 2.2 -Boyer-Moore-Horspool search algorithm
TSearch & TFileSearch Version 2.2 -Boyer-Moore-Horspool search algorithm
unit Searches;(*-----------------------------------------------------------------------------*| Components TSearch & TFileSearch || Version: 2.2 || Last Update: 10 June 2004 || Compilers: Delphi 3 - Delphi 7 || Author: Angus Johnson - angusj-AT-myrealbox-DOT-com || Copyright: © 2001 -2004 Angus Johnson || || Description: Delphi implementation of the || Boyer-Moore-Horspool search algorithm. |*-----------------------------------------------------------------------------*)//10.06.04: Added support for widestring searchesinterfaceuses windows, sysutils, classes;type TBaseSearch = class(TComponent) private fPos : pchar; fEnd : pchar; fPattern : string; fPatLen : integer; fPatInitialized : boolean; fCaseSensitive : boolean; JumpShift : integer; Shift : array[#0..#255] of integer; CaseBlindTable : array[#0..#255] of char; procedure InitPattern; procedure MakeCaseBlindTable; procedure SetCaseSensitive(CaseSens: boolean); procedure SetPattern(const Pattern: string); procedure SetWsPattern(const WsPattern: widestring); function FindCaseSensitive: integer; function FindCaseInsensitive: integer; protected fStart : pchar; fDataLength : integer; procedure ClearData; procedure SetData(Data: pchar; DataLength: integer); virtual; public constructor Create(aowner: tcomponent); override; destructor Destroy; override; //The following Find functions return the 0 based offset of Pattern //else POSITION_EOF (-1) if the Pattern is not found ... function FindFirst: integer; function FindNext: integer; function FindFrom(StartPos: integer): integer; //To simplify searching for widestring patterns - //assign the WsPattern property instead of the Pattern property property WsPattern: widestring write SetWsPattern; property Data: pchar read fStart; property DataSize: integer read fDataLength; published property CaseSensitive: boolean read fCaseSensitive write SetCaseSensitive; property Pattern: string read fPattern write SetPattern; end; TSearch = class(TBaseSearch) public //Changes visibility of base SetData() method to public ... //Note: TSearch does NOT own the data. To avoid the overhead of //copying it, it just gets a pointer to it. procedure SetData(Data: pchar; DataLength: integer); override; end; TFileSearch = class(TBaseSearch) private fFilename: string; procedure SetFilename(const Filename: string); procedure Closefile; public destructor Destroy; override; published //Assigning ‘Filename‘ creates a memory map of the named file. //This memory mapping will be closed when either the Filename property is //assigned to ‘‘ or the FileSearch object is destroyed. property Filename: string read fFilename write SetFilename; end;procedure Register;const POSITION_EOF = -1;implementationprocedure Register;begin RegisterComponents(‘Samples‘, [TSearch, TFileSearch]);end;//------------------------------------------------------------------------------// TBaseSearch methods ...//------------------------------------------------------------------------------procedure TBaseSearch.MakeCaseBlindTable;var i: char;begin for i:= #0 to #255 do CaseBlindTable[i]:= ansilowercase(i)[1];end;//------------------------------------------------------------------------------constructor TBaseSearch.Create(AOwner: TComponent);begin inherited Create(AOwner); fStart := nil; fPattern := ‘‘; fPatLen := 0; MakeCaseBlindTable; fCaseSensitive := false; //Default to case insensitive searches. fPatInitialized := false;end;//------------------------------------------------------------------------------destructor TBaseSearch.Destroy;begin ClearData; inherited Destroy;end;//------------------------------------------------------------------------------procedure TBaseSearch.ClearData;begin fStart := nil; fPos := nil; fEnd := nil; fDataLength := 0;end;//------------------------------------------------------------------------------procedure TBaseSearch.SetPattern(const Pattern: string);begin if fPattern = Pattern then exit; fPattern := Pattern; fPatLen := length(Pattern); fPatInitialized := false;end;//------------------------------------------------------------------------------procedure TBaseSearch.SetWsPattern(const WsPattern: widestring);begin fPatLen := length(WsPattern)*2; fPatInitialized := false; if fPatLen = 0 then exit; SetString(fPattern, pchar(pointer(WsPattern)), fPatLen);end;//------------------------------------------------------------------------------procedure TBaseSearch.SetData(Data: pchar; DataLength: integer);begin ClearData; if (Data = http://www.mamicode.com/nil) or (DataLength < 1) then exit; fStart := Data; fDataLength := DataLength; fEnd := fStart + fDataLength;end;//------------------------------------------------------------------------------procedure TBaseSearch.SetCaseSensitive(CaseSens: boolean);begin if fCaseSensitive = CaseSens then exit; fCaseSensitive := CaseSens; fPatInitialized := false;end;//------------------------------------------------------------------------------procedure TBaseSearch.InitPattern;var j: integer; i: char;begin if fPatLen = 0 then exit; for i := #0 to #255 do Shift[i]:= fPatLen; if fCaseSensitive then begin for j := 1 to fPatLen-1 do Shift[fPattern[j]]:= fPatLen - j; JumpShift := Shift[fPattern[fPatLen]]; Shift[fPattern[fPatLen]] := 0; end else begin for j := 1 to fPatLen-1 do Shift[CaseBlindTable[fPattern[j]]]:= fPatLen - j; JumpShift := Shift[CaseBlindTable[fPattern[fPatLen]]]; Shift[CaseBlindTable[fPattern[fPatLen]]] := 0; end; fPatInitialized := true;end;//------------------------------------------------------------------------------function TBaseSearch.FindFirst: integer;begin fPos := fStart+fPatLen-1; result := FindNext;end;//------------------------------------------------------------------------------function TBaseSearch.FindFrom(StartPos: integer): integer;begin if StartPos < fPatLen-1 then //ie: StartPos must never be less than fPatLen-1 fPos := fStart+fPatLen-1 else fPos := fStart+StartPos; result := FindNext;end;//------------------------------------------------------------------------------function TBaseSearch.FindNext: integer;begin if not fPatInitialized then InitPattern; if (fPatLen = 0) or (fPatLen >= fDataLength) or (fPos >= fEnd) then begin fPos := fEnd; result := POSITION_EOF; exit; end; if fCaseSensitive then result := FindCaseSensitive else result := FindCaseInsensitive;end;//------------------------------------------------------------------------------function TBaseSearch.FindCaseSensitive: integer;var i: integer; j: pchar;begin result:= POSITION_EOF; while fPos < fEnd do begin i := Shift[fPos^]; //test last character first if i <> 0 then //last char does not match inc(fPos,i) else begin //last char matches at least i := 1; j := fPos - fPatLen; while (i < fPatLen) and (fPattern[i] = (j+i)^) do inc(i); if (i = fPatLen) then begin result:= fPos-fStart-fPatLen+1; inc(fPos,fPatLen); break; //FOUND! end else inc(fPos,JumpShift); end; end;end;//------------------------------------------------------------------------------function TBaseSearch.FindCaseInsensitive: integer;var i: integer; j: pchar;begin result:= POSITION_EOF; while fPos < fEnd do begin i := Shift[CaseBlindTable[fPos^]]; //test last character first if i <> 0 then //last char does not match inc(fPos,i) else begin //last char matches at least i := 1; j := fPos - fPatLen; while (i < fPatLen) and (CaseBlindTable[fPattern[i]] = CaseBlindTable[(j+i)^]) do inc(i); if (i = fPatLen) then begin result:= fPos-fStart-fPatLen+1; inc(fPos,fPatLen); break; //FOUND! end else inc(fPos,JumpShift); end; end;end;//------------------------------------------------------------------------------// TSearch methods ...//------------------------------------------------------------------------------procedure TSearch.SetData(Data: pchar; DataLength: integer);begin inherited; //changes visibility of base method from protected to publicend;//------------------------------------------------------------------------------// TFileSearch methods ...//------------------------------------------------------------------------------destructor TFileSearch.Destroy;begin CloseFile; inherited Destroy;end;//------------------------------------------------------------------------------procedure TFileSearch.SetFilename(const Filename: string);var filehandle: integer; filemappinghandle: thandle; size, highsize: integer;begin if (csDesigning in ComponentState) then begin fFilename := Filename; exit; end; CloseFile; if (Filename = ‘‘) or not FileExists(Filename) then exit; filehandle := sysutils.FileOpen(Filename, fmopenread or fmsharedenynone); if filehandle = 0 then exit; //error size := GetFileSize(filehandle, @highsize); if (size <= 0) or (highsize <> 0) then //nb: files >2 gig not supported begin CloseHandle(filehandle); exit; end; filemappinghandle := CreateFileMapping(filehandle, nil, page_readonly, 0, 0, nil); if GetLastError = error_already_exists then filemappinghandle := 0; if filemappinghandle <> 0 then SetData(MapViewOfFile(filemappinghandle,file_map_read,0,0,0),size); if fStart <> nil then fFilename := Filename; CloseHandle(filemappinghandle); CloseHandle(filehandle);end;//------------------------------------------------------------------------------procedure TFileSearch.CloseFile;begin if (csDesigning in ComponentState) then exit; if (fStart <> nil) then UnmapViewOfFile(fStart); fFilename := ‘‘; ClearData;end;//------------------------------------------------------------------------------end.
TSearch & TFileSearch Version 2.2 -Boyer-Moore-Horspool search algorithm
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。