Sign in Join

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

Mailing lists / fpc-pascal / 2021-04

How does TFPGMap key compare work?

4 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

I have a question I was just curious about. From what I can tell TFPGMap uses CompareByte to compare keys of arbitrary type, which is clever but how does this work for ShortStrings? I have tried to use this method myself and I find it always fails because short strings have garbage at the end and so even if you zero out the memory (which is allocated) a short string passed as a parameter to a function will have garbage and thus fail to compare. Any ideas how this works for TFPGMap then?

function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer;
begin
  Result := CompareByte(Key1^, Key2^, FKeySize);
end;

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 6 lines
I have a question I was just curious about. From what I can tell TFPGMap uses CompareByte to compare keys of arbitrary type, which is clever but how does this work for ShortStrings? I have tried to use this method myself and I find it always fails because short strings have garbage at the end and so even if you zero out the memory (which is allocated) a short string passed as a parameter to a function will have garbage and thus fail to compare. Any ideas how this works for TFPGMap then? function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer; begin Result := CompareByte(Key1^, Key2^, FKeySize); end;

If you look at TFPSMap' code you'll see that BinaryCompareKey and BinaryCompareData are only used in the way of method pointers OnKeyPtrCompare and OnDataPtrCompare. In TFPGMap<,> these are then set to compare methods specific to the specialization, most importantly TFPGMap<,>.KeyCompare if no custom compare function is set.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Apr 20, 2021, at 3:10 PM, Sven Barth wrote: If you look at TFPSMap' code you'll see that BinaryCompareKey and BinaryCompareData are only used in the way of method pointers OnKeyPtrCompare and OnDataPtrCompare. In TFPGMap<,> these are then set to compare methods specific to the specialization, most importantly TFPGMap<,>.KeyCompare if no custom compare function is set.

There's no many levels of indirection here I got confused. I see this method below and so maybe the operators are overloaded for short strings?

function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
begin
  if PKey(Key1)^ < PKey(Key2)^ then
    Result := -1
  else if PKey(Key1)^ > PKey(Key2)^ then
    Result := 1
  else
    Result := 0;
end;

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 15 lines
> On Apr 20, 2021, at 3:10 PM, Sven Barth wrote: > > If you look at TFPSMap' code you'll see that BinaryCompareKey and BinaryCompareData are only used in the way of method pointers OnKeyPtrCompare and OnDataPtrCompare. In TFPGMap<,> these are then set to compare methods specific to the specialization, most importantly TFPGMap<,>.KeyCompare if no custom compare function is set. There's no many levels of indirection here I got confused. I see this method below and so maybe the operators are overloaded for short strings? function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer; begin if PKey(Key1)^ < PKey(Key2)^ then Result := -1 else if PKey(Key1)^ > PKey(Key2)^ then Result := 1 else Result := 0; end;

All four string types provide built in > and < operators:

=== code begin ===

program tstrcmp;
{$mode objfpc}{$H+}
var
   ss1, ss2: ShortString;
   as1, as2: AnsiString;
   us1, us2: UnicodeString;
   ws1, ws2: WideString;
begin
   ss1 := 'Hello';
   ss2 := 'World';
   as1 := 'Hello';
   as2 := 'World';
   us1 := 'Hello';
   us2 := 'World';
   ws1 := 'Hello';
   ws2 := 'World';
   Writeln('ShortString: ', ss1 < ss2, ' ', ss1 > ss2);
   Writeln('AnsiString: ', as1 < as2, ' ', as1 > as2);
   Writeln('UnicodeString: ', us1 < us2, ' ', us1 > us2);
   Writeln('WideString: ', ws1 < ws2, ' ', ws1 > ws2);
end.

=== code end ===

Regards,
Sven

Reply by email