AFAIK there's no built-in function for that. Searching the web I found this function and it works for me, but I prefer not to use it since it's assembly and I can't understand what it is doing. So I wrote this function that also works:
function Cardinality(const PSet: PByteArray;
const SizeOfSet(*in bytes*): Integer): Integer;
const
Masks: array[0..7] of Byte = (1, 2, 4, 8, 16, 32, 64, 128);
var
I, J: Integer;
begin
Result := 0;
for I := 0 to SizeOfSet - 1 do
for J := 0 to 7 do
if (PSet^[I] and Masks[J]) > 0 then
Inc(Result);
end;
Now, I want to know if I can rely on this function? Or maybe there's a trick behind the set data type and that's why delphi doesn't have a built-in method for that.
But if
my function is reliable then
how can I improve it to:
- Pass constants to it
- Do a type check and make sure that a set is passed to the function
- Pass the value instead of its address
- Get rid of
SizeOfSet
parameter
I want to call it like Cardinality(AnySet)
instead of Cardinality(@AnySet, SizeOf(TAnySet))
.
By the way, I need to compile this in both XE and XE5.
You can implement this with generics and RTTI. Like so:
Usage:
In earlier version of Delphi you can do this :