Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2021-10

Attn José: TWindowsMask oddity?

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

Hi José,

In TWindowsMask.Compile (as in your TMaskUTF8Windows class) you do a call to EscapeSpecialChars on the modified mask.
This will escape a.o. any '[' and ']' character, so ranges and sets are not possible to use in the mask anymore.

Why did you disable ranges and sets in the Windows implementation?

And another question: why do you call Compile in the constructor for TWindowsMask (TMaskUTF8Windows in your original)?

Bart

Reply by email

José Mejuto
to Bart: In TWindowsMask.Compile (as in your TMaskUTF8Windows class) you do a call to…
Bart wrote 7 lines
Hi José, In TWindowsMask.Compile (as in your TMaskUTF8Windows class) you do a call to EscapeSpecialChars on the modified mask. This will escape a.o. any '[' and ']' character, so ranges and sets are not possible to use in the mask anymore. Why did you disable ranges and sets in the Windows implementation?

Hello,

The target in *Windows classes is to mimic the old fashion CMD masks, and CMD masks does not have ranges or sets.

When I implemented that fnuction the code does not allow disabling features, so now that code can be changed to disable ranges, sets and escape char instead escaping the chars.

And another question: why do you call Compile in the constructor for TWindowsMask (TMaskUTF8Windows in your original)?

LCL's TMask raises syntax errors (or others, I can not recall) at creation time and in my code the syntax check is at Compile time so I call compile to raise an exception if needed. There is no performance loss as Compile should not be called again unless the mask is changed via the property.

Reply by email

Bart
to José Mejuto
PM José Mejuto wrote
The target in *Windows classes is to mimic the old fashion CMD masks, and CMD masks does not have ranges or sets.

OK, this is by design.
Since that is however not backwards compatible (the old mask implementation supported sets out of the box by default on all platforms, I changed "our" implementation.

A note: IIRC (do not have the source at hand here) you escape [ ] and \, with or withoud mocEscapeChar enabled.
if mocEscapeChar is not enabled, escaping these in the mask is probably not what you want.

LCL's TMask raises syntax errors (or others, I can not recall) at creation time and in my code the syntax check is at Compile time so I call compile to raise an exception if needed.
Yes, the old mask did so, whci, to be hones, is a PITA.
Normally you do
SomeVar := TSomeClass.Create(...);
try
  SomeVar.SomeThing;
finally
  SomeVar.Free
end;

If you know you can let the constructor fail, just by giving it an "invalid" parameter, you hve to rewrite you code to:

SomeVar := TSomeClass.Create(...);
if Assigned(SomeVar) then
begin
  try
    SomeVar.SomeThing;
  finally
    SomeVar.Free
  end;
end;

So, I changed it (and documented it as a change that breaks backwards compatibility).

Compile should not be called again unless the mask is changed via the property.

I think, that does not happen.
The Mask property IIRC does not have a setter.

I introduced a setter for the mask property, it sets fMaskIsCompiled to False

Also, if compile fails and the user/prgrammer is stupid enough to call Matches again, Matches will simply return False (no exception), whic (even if the programmer is stupid) is a bad thing IMO. I fixed that by setting fMaskIsCompiled to False as first line in Compile and only set it to True if Compile does not raise an exception (so it finishes).

Something else.
When you reset the mask, you should also reset the internal representation of the mask and it's associated length value, otherwise you get an access violation when you set mask via the property and then call Matches.

Again, thanks for helping me out.

Bart

Reply by email

José Mejuto
to Bart
Bart wrote 11 lines
> The target in *Windows classes is to mimic the old fashion CMD masks, > and CMD masks does not have ranges or sets. OK, this is by design. Since that is however not backwards compatible (the old mask implementation supported sets out of the box by default on all platforms, I changed "our" implementation. A note: IIRC (do not have the source at hand here) you escape [ ] and \, with or withoud mocEscapeChar enabled. if mocEscapeChar is not enabled, escaping these in the mask is probably not what you want.

Hello,

The MaskWindows is to mimic Windows behaviour, it's an implementation using the complete TMask as engine, so this class controls everything and the user (programmer) only provides a mask, can not select, or should not be able to select, which features are available in the engine. If my class works in a different way its my mistake.

In the other hand I recall why the escape is necessary instead disabling features, to mimic the "file?.dat" which must be transformed to my TMask "file[?].dat", if I left the "AnyCharOrNone" enable and disable sets and ranges this mask will not be interpreted correctly "fil[?.dat" so escaping in that function is a must.

> LCL's TMask raises syntax errors (or others, I can not recall) at > creation time and in my code the syntax check is at Compile time so I > call compile to raise an exception if needed.

[...]

So, I changed it (and documented it as a change that breaks backwards compatibility).

That's a design decision, I choose the other one based in the reason exposed.

> Compile should not be called again unless the mask is changed > via the property. I think, that does not happen. The Mask property IIRC does not have a setter.

You are right, I forget that when pusblished the Mask property.

Show quoted text 8 lines
I introduced a setter for the mask property, it sets fMaskIsCompiled to False Also, if compile fails and the user/prgrammer is stupid enough to call Matches again, Matches will simply return False (no exception), whic (even if the programmer is stupid) is a bad thing IMO. I fixed that by setting fMaskIsCompiled to False as first line in Compile and only set it to True if Compile does not raise an exception (so it finishes).

Good solution, yes.

Show quoted text 5 lines
Something else. When you reset the mask, you should also reset the internal representation of the mask and it's associated length value, otherwise you get an access violation when you set mask via the property and then call Matches.

Quite sure, yes, everything must be reseted.

Reply by email

Bart
to José Mejuto
PM José Mejuto wrote 5 lines
> A note: IIRC (do not have the source at hand here) you escape [ ] and > \, with or withoud mocEscapeChar enabled. > if mocEscapeChar is not enabled, escaping these in the mask is > probably not what you want.

...

Show quoted text 5 lines
In the other hand I recall why the escape is necessary instead disabling features, to mimic the "file?.dat" which must be transformed to my TMask "file[?].dat", if I left the "AnyCharOrNone" enable and disable sets and ranges this mask will not be interpreted correctly "fil[?.dat" so escaping in that function is a must.

Yes, I saw that you call inherited Create with TMaskOpCodesAllAllowed. So, it works as designed (ans as you expected it to work).

Show quoted text 5 lines
> So, I changed it (and documented it as a change that breaks backwards > compatibility). That's a design decision, I choose the other one based in the reason exposed.

Yes, I agree.
Of course this was not meant as criticism.

Whil at it yesterday, I also implemented read/write access for properties mask, maskopcodes, quirks for all classes that use them.

I think I also need to write a setter for AutoReverseRange property (you have it in a define, so it cannot be altered at runtime). And since I was makig all parameter in the constructor available as a r/w property, I alos should take care of CaseSensitive.

Bart

Reply by email

Bart
to Bart
PM Bart wrote
I think I also need to write a setter for AutoReverseRange property

Indeed it did.

@Jose: in the setter for EscapeChar you should also set cMaskIsCompiled to False.

Bart

Reply by email