Hello,
The current TBits.OpenBit function differs from Delphi. In Delphi, it is a read-only operation: if all allocated bits are set, it returns value equal to Size. In FPC, it expands the storage and modifies the Size property, so the result never exceeds (Size-1). This difference causes the following code to fail:
var
index: integer;
begin
index := Bits.OpenBit;
if index = Bits.Size then
AllocateSomeResourceElsewhere(); // In FPC, this is never executed
Bits[index] := True; // Bits get expanded here
end;I tried to fix that myself, but TBits code looked next to chaos for me. For example, the Clear method checks bit index and sets FBSize to (bit+1), but SetOn (which is supposed to be just complementary) does not check the index and sets FBSize to (bit) withoud adding 1; setting FBSize and FSize is scattered over several methods. So I decided to improve that, too. SetOn and Clear functionality merged into SetBit, and FBSize and FSize are changed only in SetSize.
The resulting patch is attached.
Some questions still remain, however:
1) Typing: TBitArray (classesh.inc line 308) is declared as array of Cardinal. It means that on 64-bit platforms it will consist of QWord's. Since number of bits in each element is hardcoded to 32, it looks like half of the storage will be wasted (although TBits will operate correctly). How should it be fixed: by changing Cardinal to LongWord, or by using platform-dependent values for BITSHIFT and MASK?
2) Raising 'Out of memory' error in TBits.SetSize is probably redundant because ReallocMem will do it itself?
3) Is the TBits.Size limit of 65536 necessary? I guess that it comes from Delphi, where it is caused by assembler instructions being used (BT/BTS and alike). But FPC implementation has no such limitation, so the limit looks very artificial...
Best regards,
Sergei
