- Unit Classes;
- { TBits class }
- TBits = class
- private
- FSize: Integer;
- FBits: Pointer;
- procedure Error;
- procedure SetSize(Value: Integer);
- procedure SetBit(Index: Integer; Value: Boolean);
- function GetBit(Index: Integer): Boolean;
- public
- destructor Destroy; override;
- function OpenBit: Integer;
- property Bits[Index: Integer]: Boolean read GetBit write SetBit; default;
- property Size: Integer read FSize write SetSize;
- end;
- { TBits }
- const
- BitsPerInt = SizeOf(Integer) * 8;
- type
- TBitEnum = 0..BitsPerInt - 1;
- TBitSet = set of TBitEnum;
- PBitArray = ^TBitArray;
- TBitArray = array[0..4096] of TBitSet;
- destructor TBits.Destroy;
- begin
- SetSize(0);
- inherited Destroy;
- end;
- procedure TBits.Error;
- begin
- raise EBitsError.CreateRes(@SBitsIndexError);
- end;
- procedure TBits.SetSize(Value: Integer);
- var
- NewMem: Pointer;
- NewMemSize: Integer;
- 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;
- NewMemSize := ((Value + BitsPerInt - 1) div BitsPerInt) * SizeOf(Integer);
- OldMemSize := ((Size + BitsPerInt - 1) div BitsPerInt) * SizeOf(Integer);
- if NewMemSize <> OldMemSize then
- begin
- NewMem := nil;
- if NewMemSize <> 0 then
- begin
- GetMem(NewMem, NewMemSize);
- FillChar(NewMem^, NewMemSize, 0);
- end;
- if OldMemSize <> 0 then
- begin
- if NewMem <> nil then
- Move(FBits^, NewMem^, Min(OldMemSize, NewMemSize));
- FreeMem(FBits, OldMemSize);
- end;
- FBits := NewMem;
- end;
- FSize := Value;
- end;
- end;
- procedure TBits.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 TBits.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;
- function TBits.OpenBit: Integer;
- var
- I: Integer;
- B: TBitSet;
- J: TBitEnum;
- E: Integer;
- begin
- E := (Size + BitsPerInt - 1) div BitsPerInt - 1;
- for I := 0 to E do
- if PBitArray(FBits)^[I] <> [0..BitsPerInt - 1] then
- begin
- B := PBitArray(FBits)^[I];
- for J := Low(J) to High(J) do
- begin
- if not (J in B) then
- begin
- Result := I * BitsPerInt + J;
- if Result >= Size then Result := Size;
- Exit;
- end;
- end;
- end;
- Result := Size;
- end;
- Description
- Use TBits to store and access an indefinite number of boolean values. TBits can store as many of boolean values as can fit in available memory, automatically expanding its storage space as needed. If the number of boolean values is limited to 32, the same functionality can be achieved using a 32-bit integer with the bitwise AND (Delphi) or & (C++) and OR (Delphi) or | (C++) operators.
VCL类学习之(三) TBits
最新推荐文章于 2019-08-06 15:35:59 发布