home *** CD-ROM | disk | FTP | other *** search
- {
- Basic pattern matching. Supports '*' and '?' only.
-
- This code is based on a unit by Markus Stephany (mirbir.st@t-online.de) that
- I found on DSP (http://sunsite.icm.edu.pl/delphi/). Please DO NOT email
- Markus about any problems you may find in it. All problems with it should be
- reported to me, since I'm the last one who mucked with it.
-
- The original did a bunch of stuff that I didn't need (like searching inside
- of files), didn't do some stuff that I did need (like handling spaces in the
- filename), and had a few bugs, too. In order to help me find the bugs more
- quickly, I stripped out the stuff I didn't need, renamed things to be a little
- more clear, and generally tried to clean up the mess that comes from stripping
- out stuff you don't need. :)
- }
- unit MaskSearch;
-
- interface
-
- uses
- Classes, SysUtils;
-
-
- procedure BuildMask(Str: string; MaskList: TStringList);
-
- function FileMatches(AFile: string; MaskList: TStringList): boolean;
-
-
- implementation
-
-
- // fills the grep_list with the parts of 's' (divided by ';')
- procedure BuildMask(Str: string; MaskList: TStringList);
- var
- ct: integer;
- begin
- MaskList.clear;
- MaskList.sorted := false;
- if Str = '' then
- begin
- MaskList.add('*');
- end else begin
- if Str[length(Str)] <> ';' then
- Str := Str + ';';
-
- // divide the string
- ct := Pos(';', Str);
- while ct > 0 do
- begin
- MaskList.Add(AnsiLowerCase(Copy(Str, 1, ct-1)));
- Delete(Str, 1, ct);
- ct := Pos(';', Str);
- end;
-
- MaskList.sorted := TRUE;
- MaskList.duplicates := dupIgnore;
- end;
- end;
-
- // tests whether the string 'Str' fits to the search mask in 'Mask'
- function SimpleGrep(Str, Mask: string):boolean;
- var
- sr, s2: string;
- ps1,ps2,ps3: integer;
- DontCare: boolean;
- OneChar: char;
- TmpList: TStringList;
- begin
- if (Mask = '*') or // fits always
- ((Mask = '*.*') and (Pos('.', Str) > 0)) then // always fits, too
- Result := TRUE
- else begin
- if (Pos('*', Mask) = 0) and (Pos('?', Mask) = 0) and (Mask = Str) then
- // searched text was found (searchstring IN text)
- Result := TRUE
- else begin
- Result := FALSE;
- if Mask = '' then
- exit;
-
- TmpList := TStringList.Create;
- try
- // divide partial strings ('?','*' or text) to TmpList
- repeat
- OneChar := Mask[1];
- if (OneChar in ['*', '?']) then
- begin
- TmpList.Add(OneChar);
- Delete(Mask, 1, 1);
- end else begin
- ps1 := Pos('?', Mask);
- if ps1 = 0 then
- ps1 := MaxInt;
- ps2 := Pos('*', Mask);
- if ps2 = 0 then
- ps2 := MaxInt;
- if ps2 > ps1 then
- ps2 := ps1;
-
- TmpList.Add(Copy(Mask, 1, ps2-1));
- Delete(Mask, 1, ps2-1);
- end;
- until Mask = '';
-
- // now compare the string with the partial search masks
- DontCare := FALSE;
- ps2 := 1;
- if TmpList.Count > 0 then
- begin
- for ps1 := 0 to pred(TmpList.Count) do
- begin
- sr := TmpList[ps1];
- if sr = '?' then
- begin
- inc(ps2);
- if ps2 > length(Str)+1 then
- exit;
- end else begin
- if sr = '*' then
- DontCare := TRUE
- else begin
- if DontCare then
- begin
- if ps1 = pred(TmpList.Count) then
- begin
- s2 := Copy(Str, ps2, maxint);
- ps2 := length(Str); // just something to make the thing fail
- if Length(s2) >= Length(SR) then
- if sr = Copy(s2, Length(s2)-Length(SR)+1, MaxInt) then
- ps2 := length(Str) + 1;
- end else begin
- ps3:= Pos(sr, Copy(Str, ps2, maxint));
- if ps3 = 0 then
- exit;
- ps2 := ps2 + ps3 + length(sr) - 1;
- end;
- DontCare := FALSE;
- end else begin
- if Copy(Str, ps2, length(sr)) <> sr then
- exit;
- ps2 := ps2 + length(sr);
- end;
- end;
- end;
- end;
- end;
-
- if (not DontCare) and (ps2 <> length(Str)+1) then
- Result := FALSE
- else
- Result := TRUE;
- finally
- TmpList.free;
- end;
- end;
- end;
- end;
-
- // tests whether the filename fits the search masks in MaskList
- function FileMatches(AFile: string; MaskList: TStringList): boolean;
- var
- ct: integer;
- begin
- AFile := AnsiLowerCase(AFile);
- if (MaskList = NIL) or (MaskList.Count = 0) then
- Result := TRUE // if no search AFileing, the always return TRUE
- else begin
- if Pos('.', AFile) = 0 then
- AFile := AFile + '.'; // '.' is implied for filenames
-
- Result := FALSE;
- // compare with the whole MaskList until one fits
- for ct := 0 to Pred(MaskList.Count) do
- begin
- if SimpleGrep(AFile, MaskList[ct]) then
- begin
- Result := TRUE;
- break;
- end;
- end;
- end;
- end;
-
-
- end.
-