1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| type
TMyBits = class
private
FSize: Integer;
FMemSize: Integer;
FBits: Pointer;
procedure Error;
procedure SetSize(Value: Integer);
procedure SetBit(Index: Integer; Value: Boolean);
function GetBit(Index: Integer): Boolean;
public
destructor Destroy; override;
property Bits[Index: Integer]: Boolean read GetBit write SetBit; default;
property Size: Integer read FSize write SetSize;
property MemSize: Integer read FMemSize;
end;
const
BitsPerInt = SizeOf(Integer) * 8;
destructor TMyBits.Destroy;
begin
SetSize(0);
inherited Destroy;
end;
procedure TMyBits.Error;
begin
raise EBitsError.CreateRes(@SBitsIndexError);
end;
procedure TMyBits.SetSize(Value: Integer);
var
NewMem: Pointer;
OldMemSize: Integer;
function Min(X, Y: Integer): Integer;
begin
Result := X;
if X > Y then Result := Y;
end;
begin
if Value <> Size then
begin
if Value < 0 then Error;
FMemSize := ((Value + BitsPerInt - 1) div BitsPerInt) * SizeOf(Integer);
OldMemSize := ((Size + BitsPerInt - 1) div BitsPerInt) * SizeOf(Integer);
if FMemSize <> OldMemSize then
begin
NewMem := nil;
if FMemSize <> 0 then
begin
GetMem(NewMem, FMemSize);
FillChar(NewMem^, FMemSize, 0);
end;
if OldMemSize <> 0 then
begin
if NewMem <> nil then
Move(FBits^, NewMem^, Min(OldMemSize, FMemSize));
FreeMem(FBits, OldMemSize);
end;
FBits := NewMem;
end;
FSize := Value;
end;
end;
procedure TMyBits.SetBit(Index: Integer; Value: Boolean); assembler;
asm
CMP Index,[EAX].FSize
JAE @@Size
@@1: MOV EAX,[EAX].FBits
OR Value,Value
JZ @@2
BTS [EAX],Index
RET
@@2: BTR [EAX],Index
RET
@@Size: CMP Index,0
JL TBits.Error
PUSH Self
PUSH Index
PUSH ECX {Value}
INC Index
CALL TBits.SetSize
POP ECX {Value}
POP Index
POP Self
JMP @@1
end;
function TMyBits.GetBit(Index: Integer): Boolean; assembler;
asm
CMP Index,[EAX].FSize
JAE TBits.Error
MOV EAX,[EAX].FBits
BT [EAX],Index
SBB EAX,EAX
AND EAX,1
end; |
Partager