Why not the simplest?
in my case, the testforskip() was complex and only needed to one once before the data started streaming.
So in the end I found I needed both a SET and a bit mask to keep thing fast so I created an object that holds one of each. then when I added a channel, a bit in the mask would also be set and vis versa. here is my code to share for this topic since all of you helped.
<FYI this code is not yet tested>
type
TChanListSets = object
private { private declarations }
MySlots : PktDataSlots;
MyMask : U32;
procedure SetMask(AValue: U32);
procedure SetSlots(AValue: PktDataSlots);
public { public declarations }
count : Integer;
property Slots : PktDataSlots read MySlots write SetSlots;
property Mask : U32 read MyMask write SetMask;
procedure AddChan(ch:Integer);
procedure RemoveChan(ch:Integer);
procedure Clear();
end;
...
procedure TChanListSets.Clear();
begin
MyMask := 0;
count := 0;
MySlots:= []; // empty set
end;
procedure TChanListSets.SetMask(AValue: U32);
var i,msk :U32;
begin
Avalue := (Avalue and CHANNEL_MSK_24);
if MyMask =AValue then
Exit;
MyMask :=AValue;
MySlots :=[]; // empty set
count := 0;
if (Avalue = 0) then
exit;
// removed some predefined sets here that were commonly used that just set the SET and Mask
// <snip>
msk := 1;
i := 1;
repeat
if ((msk and Avalue)>0) then begin
Avalue := Avalue xor msk; // clr the bit
Include(MySlots, i);
inc(count);
end;
msk := msk shl 1;
inc(i);
until (avalue = 0) or (i > 30);
end;
procedure TChanListSets.SetSlots(AValue: PktDataSlots); // set SETs to a value
var i :Integer;
begin
if MySlots = AValue then
Exit;
MySlots :=AValue;
MyMask := 0;
count := 0;
for i in MySlots do begin // keep the mask in sync
MyMask :=MyMask or (1 shl i-1);
inc(count);
end;
end;
procedure TChanListSets.AddChan(ch: Integer);
var msk:U32;
begin
if (ch < 1) or (ch > MaxCalChannels) then begin
Exception.Create('channel value of '+IntToStr(ch)+' Out Of Range[1..30]');
exit;
end;
msk := MyMask;
MyMask := MyMask or (1 shl ch-1);
if (msk = MyMask) then
exit;
Include(MySlots,ch);
inc(count);
end;
procedure TChanListSets.RemoveChan(ch: Integer);
var msk:U32;
begin
if (ch < 1) or (ch > MaxCalChannels) then begin
Exception.Create('channel value of '+IntToStr(ch)+' Out of Range[1..30]');
exit;
end;
msk := MyMask;
MyMask := MyMask and not(1 shl ch-1);
if (msk = MyMask) then
exit;
Exclude(MySlots,ch);
dec(count);
end;
Now I have both a list of channels and a channel mask I can use in my final code. I used an object instead of a class due to the fact it will be included in another class and I do not need a separate create() or destroy() yet.