mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 23:49:22 +02:00
* fixes and cleanups for tbits (patch by Sergei Gorelkin, mantis #13890)
git-svn-id: trunk@13243 -
This commit is contained in:
parent
7bff50becd
commit
ba951580a2
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
32
tests/webtbs/tw13890.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user