Discussion:
[fpc-pascal] How does TFPGMap key compare work?
Ryan Joseph via fpc-pascal
2021-04-19 17:05:55 UTC
Permalink
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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinf
Sven Barth via fpc-pascal
2021-04-20 21:10:36 UTC
Permalink
Post by Ryan Joseph via fpc-pascal
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc
Ryan Joseph via fpc-pascal
2021-04-20 22:09:14 UTC
Permalink
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

_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.fre
Sven Barth via fpc-pascal
2021-04-21 05:38:40 UTC
Permalink
Post by Ryan Joseph via fpc-pascal
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
_______________________________________________
fpc-pascal maillist - fpc-***@lists.freepascal.org
https://lists.freepascal.org/cgi

Loading...