home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 September
/
Chip_2001-09_cd1.bin
/
zkuste
/
delphi
/
kolekce
/
d123456
/
DFS.ZIP
/
MaskSearch.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-12-10
|
5KB
|
186 lines
{
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.