views:

166

answers:

2

I have been experimenting with TMask in Delphi 2010 and it seems to work as expected except in one situation: when the mask name contains [ or ] the mask always seem to return false. For example:

var
  MaskObj : TMask;
begin
  MaskObj:= TMask.Create('c:\[test]\*');
  try
    Result:= MaskObj.Matches('c:\[test]\text');
  finally
    FreeAndNil(MaskObj);
  end;
end;

returns false. ...

Yes, [ and ] are legal characters in file name. So if I want to exclude for example all files in c:[test]*, what could I do here? My only solution is to do a StringReplace if [ is detected, but this will be slow for a large number of files:

if (pos('[', Mask)>0) then
begin
  mask:= ReplaceString(Mask, '[','_', etc...
  // and do the same for the file name---
end;

Is there any other approach?

+3  A: 

'[' is used to mark the beginning of a set of characters (eg, "[A-Z]"). In order to match '[' on its own you just need to create it as its own single-character set. ']' doesn't need to be similarly escaped, since it's only a special character once a leading '[' is found. Try C:\[[]test]\*

Edit:

If you're allowing arbitrary masks you'll need to use StringReplace(Mask, '[', '[[]', [rfReplaceAll]) for the mask, but not for the filenames. If you never use the [a-z] wildcards I'd just descend from TMask and handle it in the constructor.

Craig Peterson
So basically you still need the StringReplace calls. You can make it faster by removing the `if pos` calls, though, since stringReplace does that internally.
Mason Wheeler
A: 

Be very careful when you try to use MatchesMask for paths. There are more problems than the one exposed here. See this blog post for details.

To fix it, you could split the path and the file name (if your usage case allows it), copy the Masks.pas unit in your project directory (in order to be compiled instead of the 'official' Masks unit) and disable the '[' processing, in order to have no speed penalties.

HTH