resourcestring
rsSetTooLarge = 'Set too large';
rsNotaSet = 'Not a set';
rsEmptySet = 'Empty set';
{...}
function FirstInSet<T{:set}>(aSet: T): SizeUInt; inline;
type
HWord = record a,b,c,d: QWord; end; PHWord = ^HWord;
var
pTail: PByte;
begin
if GetTypeKind(T) = tkSet then begin
Result:= 255;
case SizeOf(T) div 8 of
1: Result:= BsfQWord(PHWord(@aSet)^.a);
2: begin
Result:= BsfQWord(PHWord(@aSet)^.a);
if Result = 255 then begin
Result:= BsfQWord(PHWord(@aSet)^.b);
if Result <> 255 then
inc(Result, 64);
end;
end;
3: begin
Result:= BsfQWord(PHWord(@aSet)^.a);
if Result = 255 then begin
Result:= BsfQWord(PHWord(@aSet)^.b);
if Result = 255 then begin
Result:= BsfQWord(PHWord(@aSet)^.c);
if Result <> 255 then
inc(Result, 128);
end else inc(Result, 64);
end;
end;
4: begin
Result:= BsfQWord(PHWord(@aSet)^.a);
if Result = 255 then begin
Result:= BsfQWord(PHWord(@aSet)^.b);
if Result = 255 then begin
Result:= BsfQWord(PHWord(@aSet)^.c);
if Result = 255 then begin
Result:= BsfQWord(PHWord(@aSet)^.d);
if Result = 255
then raise ESetException.Create(rsEmptySet)
else Exit(Result + 192);
end else inc(Result, 128);
end else inc(Result, 64);
end;
end;
end;
if Result = 255 then begin
pTail:= @aSet + (SizeOf(T) and -8);
case SizeOf(T) mod 8 of
1: Result:= BsfByte(PByte(pTail)^);
2: Result:= BsfWord(PWord(pTail)^);
3: Result:= BsfDWord(PWord(pTail)^ + PByte(pTail + 2)^ shl 16);
4: Result:= BsfDWord(PDWord(pTail)^);
5: Result:= BsfQWord(PDWord(pTail)^ + QWord(PByte(pTail + 4)^) shl 32);
6: Result:= BsfQWord(PDWord(pTail)^ + QWord(PWord(pTail + 4)^) shl 32);
7: Result:= BsfQWord(PDWord(pTail)^ + QWord(PWord(pTail + 4)^) shl 32 + QWord(PByte(pTail + 6)^) shl 48);
end;
if Result = 255
then raise ESetException.Create(rsEmptySet)
else inc(Result, 64 * (SizeOf(T) div 8));
end;
end else raise ESetException.Create(rsNotaSet);
end;