How to simulate bit-fields in Delphi records?

前端 未结 4 2065
终归单人心
终归单人心 2020-12-04 18:32

I would like to declare a record in Delphi that contains the same layout as it has in C.

For those interested : This record is part of a union in the Windows OS\'s L

4条回答
  •  囚心锁ツ
    2020-12-04 18:55

    Ok, my bit manipulation is a bit rusty, so I could have reversed the bytes. But the code below gives the general idea:

    type
      TBits = record
      private
        FBaseMid     : Byte;
        FTypeDplPres :  Byte;
        FLimitHiSysEa: Byte;
        FBaseHi      : Byte;
    
        function GetType: Byte;
        procedure SetType(const AType: Byte);
        function GetDpl: Byte;
        procedure SetDbl(const ADpl: Byte);
        function GetBit1(const AIndex: Integer): Boolean;
        procedure SetBit1(const AIndex: Integer; const AValue: Boolean);
        function GetLimitHi: Byte;
        procedure SetLimitHi(const AValue: Byte);
        function GetBit2(const AIndex: Integer): Boolean;
        procedure SetBit2(const AIndex: Integer; const AValue: Boolean);
    
      public
        property BaseMid: Byte read FBaseMid write FBaseMid;
        property &Type: Byte read GetType write SetType; // 0..31
        property Dpl: Byte read GetDpl write SetDbl; // 0..3
        property Pres: Boolean index 128 read GetBit1 write SetBit1; 
        property LimitHi: Byte read GetLimitHi write SetLimitHi; // 0..15
    
        property Sys: Boolean index 16 read GetBit2 write SetBit2; 
        property Reserved0: Boolean index 32 read GetBit2 write SetBit2; 
        property DefaultBig: Boolean index 64 read GetBit2 write SetBit2; 
        property Granularity: Boolean index 128 read GetBit2 write SetBit2; 
        property BaseHi: Byte read FBaseHi write FBaseHi;
      end;
    
      function TBits.GetType: Byte;
      begin
        Result := (FTypeDplPres shr 3) and $1F;
      end;
    
      procedure TBits.SetType(const AType: Byte);
      begin
        FTypeDplPres := (FTypeDplPres and $07) + ((AType and $1F) shr 3);
      end;
    
      function TBits.GetDpl: Byte;
      begin
        Result := (FTypeDplPres and $06) shr 1;
      end;
    
      procedure TBits.SetDbl(const ADpl: Byte);
      begin
        FTypeDblPres := (FTypeDblPres and $F9) + ((ADpl and $3) shl 1);
      end;
    
      function TBits.GetBit1(const AIndex: Integer): Boolean;
      begin
        Result := FTypeDplPres and AIndex = AIndex;
      end;
    
      procedure TBits.SetBit1(const AIndex: Integer; const AValue: Boolean);
      begin
        if AValue then
          FTypeDblPres := FTypeDblPres or AIndex
        else
          FTypeDblPres := FTypeDblPres and not AIndex;
      end;
    
      function TBits.GetLimitHi: Byte;
      begin
        Result := (FLimitHiSysEa shr 4) and $0F;
      end;
    
      procedure TBits.SetLimitHi(const AValue: Byte);
      begin
        FLimitHiSysEa := (FLimitHiSysEa and $0F) + ((AValue and $0F) shr 4);
      end;
    
      function TBits.GetBit2(const AIndex: Integer): Boolean;
      begin
        Result := FLimitHiSysEa and AIndex = AIndex;
      end;
    
      procedure TBits.SetBit2(const AIndex: Integer; const AValue: Boolean);
      begin
        if AValue then
          FLimitHiSysEa := FLimitHiSysEa or AIndex
        else
          FLimitHiSysEa := FLimitHiSysEa and not AIndex;
      end;
    

提交回复
热议问题