//Autor: Wiesław Dudek
//

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons;

type
  TMainForm = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    Memo1: TMemo;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    OpenDialog1: TOpenDialog;
    procedure BitBtn2Click(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private declarations }
    procedure WyszukajIdentyfikatory(aFileName : string; aIdentLength : integer);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}                    

procedure TMainForm.BitBtn2Click(Sender: TObject);
begin
  Close ;
end;

procedure TMainForm.BitBtn1Click(Sender: TObject);
var i : integer ;
begin
  OpenDialog1.InitialDir:=GetCurrentDir ;
  if OpenDialog1.Execute then
  begin
    Memo1.Clear ;
    if StrToIntDef(Edit1.text,-1)=-1 then
      Memo1.Lines.Add('Wyszukane frazy: '+Edit1.text)
    else Memo1.Lines.Add('Wyszukane identyfikatory o długości '+Edit1.text+' znaków.') ;
    for i:=1 to OpenDialog1.Files.Count do
      WyszukajIdentyfikatory(OpenDialog1.Files[i-1],StrToIntDef(Edit1.Text,10)) ;
  end ;
end;

(*function search( pat: PATTERN; text: TEXT ): integer;
var i, j, k, m, n: integer;
  skip: array [0..MAXCHAR] of integer;
  found: boolean;
begin
  found := FALSE; search := 0;
  m := length(pat);
  if m=0 then
  begin
    search := 1;
    found := TRUE;
  end;
  for k:=0 to MAXCHAR do skip[k] := m;   {*** Preprocessing ***}
  for k:=1 to m-1 do
    skip[ord(pat[k])] := m-k;

  k:= m;
  n:= length(text);            {*** Search ***}
  while not found and (k <= n) do
  begin
    i := k;
    j := m;
    while (j >= 1) do
      if text[i] <> pat[j] then j := -1
      else begin
        j := j-1;  i := i-1;
      end;
    if j = 0 then
    begin
      search := i+1;
      found := TRUE;
    end;
    k:= k + skip[ord(text[k])];
  end;
end;*)

{Algorytm: Boyer-Moore-Horspool}

function Search(pat: string; text: Pointer; aSize : integer ): integer;
const MAXCHAR=255 ;
var i, j, k, m, n: integer;
  skip: array [0..MAXCHAR] of integer;
  found: boolean;
begin
  found := FALSE;
  search := 0;
  m := length(pat);
  if m=0 then
  begin
    search := 1;
    found := TRUE;
  end;
  for k:=0 to MAXCHAR do skip[k] := m;   {*** Preprocessing ***}
  for k:=1 to m-1 do
    skip[ord(pat[k])] := m-k;

  k:= m;
  n:= aSize;            {*** Search ***}
  while not found and (k <= n) do
  begin
    i := k;
    j := m;
    while (j >= 1) do
    begin
      if char((Pointer(integer(text)+i))^) <> pat[j] then j := -1
      else begin
        j := j-1;
        i := i-1;
      end;
    end ;
    if j = 0 then
    begin
      search := i+1;
      found := TRUE;
    end;
    k:= k + skip[ord(char((Pointer(integer(text)+i))^))];
  end;
end;

function SearchIdent(aIdentLength : integer; text: Pointer; aSize : integer ): TStringList;
const ValidChars=['a'..'z','A'..'Z','0'..'9'] ;
      NumberChars=['0'..'9'] ;
var dl,i,j : integer ;
    temp : string ;
begin
  Result:=TStringList.Create ;
  dl:=0 ;
  for i:=0 to aSize do
    if char((Pointer(integer(text)+i))^) in ValidChars then
      if (dl=0) and (char((Pointer(integer(text)+i))^) in NumberChars) then
      else inc(dl)
    else
      if dl<>0 then
      begin
        if dl>=aIdentLength then
        begin
          temp:='' ;
          for j:=i-dl to i-1 do
            temp:=temp+char((Pointer(integer(text)+j))^) ;
          Result.Add(temp) ;
        end ;
        dl:=0 ;
      end ;
end ;

procedure TMainForm.WyszukajIdentyfikatory(aFileName : string; aIdentLength : integer);
var  FHandleOfMapFile, FHandleOfFile : THandle ;
     i, Gdzie, FSizeOfFile : integer ;
     FPointerOfData : Pointer ;
     ww : TStringList ;
begin
  if not FileExists(aFileName) then
    raise Exception.Create('Brak pliku '+aFileName)
  else FHandleOfFile:=FileOpen(aFileName,fmOpenRead) ;
  if FHandleOfFile=INVALID_HANDLE_VALUE then
    raise Exception.Create('Otwarcie pliku '+aFileName+' nie powiodło się.'#13'Błąd: '+SysErrorMessage(GetLastError)) ;
  try
    FSizeOfFile:=GetFileSize(FHandleOfFile,Nil) ;
    FHandleOfMapFile:=CreateFileMapping(FHandleOfFile,nil,PAGE_READONLY,0,FSizeOfFile,nil) ;
    if FHandleOfMapFile=0 then
      raise Exception.Create('Nie udało się utworzyć obiektu odwzorowującego.'#13'Błąd: '+SysErrorMessage(GetLastError)) ;
  finally
    CloseHandle(FHandleOfFile) ;
  end ;
  try
    FPointerOfData:=MapViewOfFile(FHandleOfMapFile,FILE_MAP_READ,0,0,FSizeOfFile) ;
    if FPointerOfData=nil then
      raise Exception.Create('Nie udało się utworzyć widoku odwzorowania.'#13'Błąd: '+SysErrorMessage(GetLastError)) ;
  finally
    CloseHandle(FHandleOfMapFile) ;
  end ;
  try
    //wyszukiwanie
    if StrToIntDef(Edit1.text,-1)=-1 then
    begin
      Gdzie:=Search(Edit1.text,FPointerOfData,FSizeOfFile) ;
      if Gdzie<>0 then
        Memo1.Lines.Add(aFileName+'; Pozycja: '+inttostr(Gdzie)) ;
    end
    else begin
      ww:=SearchIdent(StrToIntDef(Edit1.text,-1),FPointerOfData,FSizeOfFile) ;
      if ww.count>0 then
      begin
        Memo1.Lines.Add(aFileName+'; Identyfikatory: ') ;
        for i:=1 to ww.Count do
          Memo1.Lines.Add(ww.Strings[i-1]) ;
      end ;
    end ;
  finally
    UnMapViewOfFile(FPointerOfData) ;
  end ;
end ;

end.
