Link to home
Start Free TrialLog in
Avatar of mhervais
mhervais

asked on

Did you know that

TstringsList.IndexOf was case insensitive ?

the online help don't say that :-((
Avatar of scrapdog
scrapdog
Flag of United States of America image

That is because the IndexOf method uses AnsiCompareText, which calls the API function CompareString with the flag NORM_IGNORECASE set.

To make TStrings.IndexOf case sensitive, you could override ride it using the follow code:

function TStrings.IndexOfName(const Name: string): Integer;
var
  P: Integer;
  S: string;
begin
  for Result := 0 to GetCount - 1 do
  begin
    S := Get(Result);
    P := AnsiPos('=', S);
    if (P <> 0) and (AnsiCompareStr(Copy(S, 1, P - 1), Name) = 0) then Exit;
  end;
  Result := -1;
end;

AnsiCompareStr calls CompareString with all flags cleared.

Avatar of mhervais
mhervais

ASKER

thanks scrapdog. I will increase the points for you.

I suppose that if you issue a getcount function instead of using the count property, and if you issue a get rather than to look for items[result] it is for reasons of performance ?

Do I have to do the same for the find function ?
Avatar of simonet
This is the source code I have for the IndexOf() function:

function TStrings.IndexOf(const S: string): Integer;
begin
  for Result := 0 to GetCount - 1 do
    if AnsiCompareText(Get(Result), S) = 0 then Exit;
  Result := -1;
end;

AnsiCompareText is not case sensitive.

Answering your questions, mhervais:

>I suppose that if you issue a getcount function instead of
>using the count property

That won't make any difference, because GetCount is a protected method, thus your application cannot see it. Second because the Count property directly accesses the GetCount protected method:

    property Count: Integer read GetCount;

>if you issue a get rather than to look for items[result]
>it is for reasons of performance ?

Doesn't matter either. The Strings[] property is defined as:

    property Strings[Index: Integer]: string read Get write Put; default;

So you 'll be accessing the Get function anyway. Besides, again, Get is a protected function and you do not have access to it.

There are hacks you can do to have access to protected methods, but since TStrings and its descedant, TStringList, already exposes all the useful stuff, there's not need to hack its protected method. You'll won't be improving anything anyway.

Yours,

Alex

Thanks Alex. In the mean time I overrid the find function by modifiyng a copy of the VCL function.

ScrapDog gave the clue, howether his function does not work
I think the points should go to him.

Here are the two overridden functions that works :

function MyTStringList.Find(const S: string; var Index: Integer): Boolean;
var
  I: Integer;
  L: Integer;
  H: Integer;
  C: Integer;
begin
  Result := False;
  L := 0;
  H := GetCount - 1;
  while L <= H do
  begin
    I := (L + H) shr 1;
    C := AnsiCompareStr(Strings[i], S);
    if C < 0 then L := I + 1 else
    begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        if Duplicates <> dupAccept then L := I;
      end;
    end;
  end;
  Index := L;
end;

function MyTStringList.IndexOf(const Name :string): Integer;
begin
for Result := 0 to GetCount - 1 do
begin
  if AnsiCompareStr(Get(Result), Name) = 0 then Exit;
end;
Result := -1;
end;
ASKER CERTIFIED SOLUTION
Avatar of scrapdog
scrapdog
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well I did not see that you answered with a TStrings example, because my question was about TStringList.

TStringList stores strings and objects, and I would not have to take what is on the right of the equal sign.

regards, Marc  
I wasn't aware that TStringList.IndexOf existed until I just checked the help-file...I assumed you meant TStringList.Strings.IndexOf...my mistake...