* fixes and cleanups for tbits (patch by Sergei Gorelkin, mantis #13890)

git-svn-id: trunk@13243 -
This commit is contained in:
Jonas Maebe 2009-06-06 14:35:25 +00:00
parent 7bff50becd
commit ba951580a2
4 changed files with 93 additions and 100 deletions

1
.gitattributes vendored
View File

@ -9156,6 +9156,7 @@ tests/webtbs/tw1376.pp svneol=native#text/plain
tests/webtbs/tw13763.pp svneol=native#text/plain tests/webtbs/tw13763.pp svneol=native#text/plain
tests/webtbs/tw13813.pp svneol=native#text/plain tests/webtbs/tw13813.pp svneol=native#text/plain
tests/webtbs/tw13820.pp svneol=native#text/plain tests/webtbs/tw13820.pp svneol=native#text/plain
tests/webtbs/tw13890.pp svneol=native#text/plain
tests/webtbs/tw1398.pp svneol=native#text/plain tests/webtbs/tw1398.pp svneol=native#text/plain
tests/webtbs/tw1401.pp svneol=native#text/plain tests/webtbs/tw1401.pp svneol=native#text/plain
tests/webtbs/tw1407.pp svneol=native#text/plain tests/webtbs/tw1407.pp svneol=native#text/plain

View File

@ -14,13 +14,13 @@
{* TBits *} {* TBits *}
{****************************************************************************} {****************************************************************************}
Procedure BitsError (Msg : string); Procedure BitsError (const Msg : string);
begin begin
Raise EBitsError.Create(Msg) at get_caller_addr(get_frame); Raise EBitsError.Create(Msg) at get_caller_addr(get_frame);
end; end;
Procedure BitsErrorFmt (Msg : string; const Args : array of const); Procedure BitsErrorFmt (const Msg : string; const Args : array of const);
begin begin
Raise EBitsError.CreateFmt(Msg,args) at get_caller_addr(get_frame); Raise EBitsError.CreateFmt(Msg,args) at get_caller_addr(get_frame);
@ -43,88 +43,73 @@ begin
end; end;
procedure TBits.Resize(Nbit: longint);
var
newSize : longint;
loop : longint;
begin
CheckBitindex(nbit,false);
newSize := (nbit shr BITSHIFT) + 1;
if newSize <> FSize then
begin
ReAllocMem(FBits, newSize * SizeOf(longint));
if FBits <> nil then
begin
if newSize > FSize then
for loop := FSize to newSize - 1 do
FBits^[loop] := 0;
FSize := newSize;
FBSize := nbit + 1;
end
else
BitsError(SErrOutOfMemory);
end;
end;
{ ************* functions to match TBits class ************* } { ************* functions to match TBits class ************* }
function TBits.getSize : longint; procedure TBits.setSize(value: longint);
var
newSize, loop: LongInt;
begin begin
result := FBSize; CheckBitIndex(value, false);
end;
procedure TBits.setSize(value : longint); if value <> 0 then
begin newSize := (value shr BITSHIFT) + 1
if value=0 then else
resize(0) // truncate newSize := 0;
else
Resize(value - 1); if newSize <> FSize then
FBSize:= value; begin
ReAllocMem(FBits, newSize * SizeOf(longint));
if FBits <> nil then
begin
if newSize > FSize then
for loop := FSize to newSize - 1 do
FBits^[loop] := 0;
end
else if newSize > 0 then
BitsError(SErrOutOfMemory); { isn't ReallocMem supposed to throw EOutOfMemory? }
FSize := newSize;
end;
FBSize := value;
end; end;
procedure TBits.SetBit(bit : longint; value : Boolean); procedure TBits.SetBit(bit : longint; value : Boolean);
var
n: Integer;
begin begin
if value = True then grow(bit+1); { validates bit range and adjusts FBSize if necessary }
seton(bit) n := bit shr BITSHIFT;
else if value then
clear(bit); FBits^[n] := FBits^[n] or (longword(1) shl (bit and MASK))
else
FBits^[n] := FBits^[n] and not (longword(1) shl (bit and MASK));
end; end;
function TBits.OpenBit : longint; function TBits.OpenBit : longint;
var var
loop : longint; loop : longint;
loop2 : longint; loop2 : longint;
startIndex : longint;
stopIndex : Longint;
begin begin
result := -1; {should only occur if the whole array is set} result := -1; {should only occur if the whole array is set}
for loop := 0 to FSize - 1 do { map 0 to -1, 1..32 to 0, etc }
for loop := 0 to ((FBSize + MASK) shr BITSHIFT) - 1 do
begin begin
if FBits^[loop] <> $FFFFFFFF then if FBits^[loop] <> $FFFFFFFF then
begin begin
startIndex := loop * 32; for loop2 := 0 to MASK do
stopIndex := liMin ( FBSize -1,startIndex + 31) ;
for loop2 := startIndex to stopIndex do
begin begin
if get(loop2) = False then if (FBits^[loop] and (longint(1) shl loop2)) = 0 then
begin begin
result := loop2; result := (loop shl BITSHIFT) + loop2;
break; { use this as the index to return } if result > FBSize then
end; result := FBSize;
end; Exit;
if result = -1 then begin
result := FBSize;
inc(FBSize);
end; end;
break; {stop looking for empty bit in records } end;
end; end;
end; end;
if result = -1 then if FSize < MaxBitRec then
if FSize < MaxBitRec then result := FSize * 32; {first bit of next record}
result := FSize * 32; {first bit of next record}
end; end;
{ ******************** TBits ***************************** } { ******************** TBits ***************************** }
@ -136,7 +121,7 @@ begin
FBits := nil; FBits := nil;
findIndex := -1; findIndex := -1;
findState := True; { no reason just setting it to something } findState := True; { no reason just setting it to something }
if TheSize > 0 then grow(theSize-1); if TheSize > 0 then grow(theSize);
end; end;
destructor TBits.Destroy; destructor TBits.Destroy;
@ -148,12 +133,10 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TBits.grow(nbit : longint); procedure TBits.grow(nbit: longint);
var
newSize : longint;
begin begin
newSize := (nbit shr BITSHIFT) + 1; if nbit > FBSize then
if newSize > FSize then Resize(nbit); SetSize(nbit);
end; end;
function TBits.getFSize : longint; function TBits.getFSize : longint;
@ -162,24 +145,13 @@ begin
end; end;
procedure TBits.seton(bit : longint); procedure TBits.seton(bit : longint);
var
n : longint;
begin begin
n := bit shr BITSHIFT; SetBit(bit, True);
grow(bit);
FBits^[n] := FBits^[n] or (cardinal(1) shl (bit and MASK));
if bit >= FBSize then FBSize := bit;
end; end;
procedure TBits.clear(bit : longint); procedure TBits.clear(bit : longint);
var
n : longint;
begin begin
CheckBitIndex(bit,false); SetBit(bit, False);
n := bit shr BITSHIFT;
grow(bit);
FBits^[n] := FBits^[n] and not(longint(1) shl (bit and MASK));
if bit >= FBSize then FBSize := bit + 1;
end; end;
procedure TBits.clearall; procedure TBits.clearall;
@ -188,8 +160,8 @@ var
begin begin
for loop := 0 to FSize - 1 do for loop := 0 to FSize - 1 do
FBits^[loop] := 0; FBits^[loop] := 0;
{Should FBSize be cleared too? - I think so} { don't clear FBSize here, it will cause exceptions on subsequent reading bit values }
FBSize := 0; { use 'Size := 0' to reset everything and deallocate storage }
end; end;
function TBits.get(bit : longint) : Boolean; function TBits.get(bit : longint) : Boolean;
@ -240,33 +212,23 @@ end;
procedure TBits.orbits(bitset : TBits); procedure TBits.orbits(bitset : TBits);
var var
n : longint;
loop : longint; loop : longint;
begin begin
if FSize < bitset.getFSize then if FBSize < bitset.Size then
n := bitset.getFSize - 1 grow(bitset.Size);
else
n := FSize - 1;
grow(n shl BITSHIFT); for loop := 0 to FSize-1 do
for loop := 0 to n do
FBits^[loop] := FBits^[loop] or bitset.FBits^[loop]; FBits^[loop] := FBits^[loop] or bitset.FBits^[loop];
end; end;
procedure TBits.xorbits(bitset : TBits); procedure TBits.xorbits(bitset : TBits);
var var
n : longint;
loop : longint; loop : longint;
begin begin
if FSize < bitset.getFSize then if FBSize < bitset.Size then
n := bitset.getFSize - 1 grow(bitset.Size);
else
n := FSize - 1;
grow(n shl BITSHIFT); for loop := 0 to FSize-1 do
for loop := 0 to n do
FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop]; FBits^[loop] := FBits^[loop] xor bitset.FBits^[loop];
end; end;

View File

@ -318,10 +318,8 @@ type
{ functions and properties to match TBits class } { functions and properties to match TBits class }
procedure SetBit(bit : longint; value : Boolean); procedure SetBit(bit : longint; value : Boolean);
function GetSize : longint;
procedure SetSize(value : longint); procedure SetSize(value : longint);
procedure CheckBitIndex (Bit : longint;CurrentSize : Boolean); procedure CheckBitIndex (Bit : longint;CurrentSize : Boolean);
procedure Resize(Nbit : longint);
public public
{ Public declarations } { Public declarations }
constructor Create(TheSize : longint = 0); virtual; constructor Create(TheSize : longint = 0); virtual;
@ -345,7 +343,7 @@ type
{ functions and properties to match TBits class } { functions and properties to match TBits class }
function OpenBit: longint; function OpenBit: longint;
property Bits[Bit: longint]: Boolean read get write SetBit; default; property Bits[Bit: longint]: Boolean read get write SetBit; default;
property Size: longint read getSize write setSize; property Size: longint read FBSize write setSize;
end; end;
{ TPersistent abstract class } { TPersistent abstract class }

32
tests/webtbs/tw13890.pp Normal file
View File

@ -0,0 +1,32 @@
program test_bits;
{$ifdef fpc}{$mode objfpc}{$h+}{$endif}
uses Classes;
var
bits: TBits;
i, j: Integer;
count: Integer;
procedure AllocateSomething;
begin
Inc(count);
end;
begin
bits := TBits.Create;
count := 0;
for i := 0 to 9 do
begin
j := bits.OpenBit;
if j = bits.Size then
begin
AllocateSomething;
bits[j] := True;
end;
end;
bits.Free;
writeln(count);
if count <> 10 then
Halt(1);
end.