PDA

View Full Version : Convert set to binary representation



chronozphere
01-04-2011, 09:19 AM
Hey everyone,

I have the following types:



TMyType = (mtOne = 1, mtTwo = 2, mtFour = 4, mtEight = 8);

TMySet = set of TMyType;


Now I want to define a function that takes a set of TMyType and turns it into a binary representation of that set (a.k.a Flags).

I've done the following:



r := 0;
for I := low(TMyType) to high(TMyType) do
if I in s then
r := r or Integer(I);


It works but there are some drawbacks:
> It only works for TMyType. I have to define a load of other ones if I have many set types that need conversion.
> It doesn't perform well when TMyType contains elements representing large numbers. The loop will go through all numbers between low(TMyType) and high(TMyType). This is really wastefull because in this case, I'd only use 1,2,4,8,16 etc..

Is there any better way of converting sets to binary representation? I feel that this would be a very powerfull feature. It allows you to make better wrappers for C libraries that make use of flags. Sets are much easier to use and are more high-level. :)

Thanks

vgo
01-04-2011, 10:50 AM
Maybe like this?



procedure Foo;
var
Mask, Index: LongWord;
s: TMySet;
begin
s := [mtOne, mtTwo, mtSixteen];
Index := 1;
Mask := 0;
while Index <= Integer(High(TMyType)) do
begin
if TMyType(Index) in s then
Mask := Mask or Index;
Index := Index * 2;
end;
end;

Dan
02-04-2011, 07:11 AM
You guys are overdoing it a bit. Delphi already stores sets in the form of flags (only difference is that it uses 16 bytes of memory instead of 4 byte dword), so all you need to do to get your flags is type cast the set to a dword like this:
Flags := LongWord(AnySet);
if you want this to work you will have to use enumeration range from 0 to 31 (type TMyEnum = (meOne, meTwo{these are fine}, meThrityThree = 32{this will be out of range for a dword});)