Sign in Join
Wiki copytemporary

Bit manipulation: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Bit manipulation

OldNewLine
1+## Masked operations
2+
3+This is a basic low level approach to handle bit manipulation. Main advantage is that operations can be performed with groups of bits at once. But the user has to deal with all operations by himself. Another problem is max range of used values in function parameters. There must be separate implemented functions for each ordinal type for best performance (as opposed to C templates using preprocessor).
4+
5+``` pascal
6+procedure ClearBit(var Value: QWord; Index: Byte);
7+begin
8+ Value := Value and ((QWord(1) shl Index) xor High(QWord));
9+end;
10+
11+procedure SetBit(var Value: QWord; Index: Byte);
12+begin
13+ Value:= Value or (QWord(1) shl Index);
14+end;
15+
16+procedure PutBit(var Value: QWord; Index: Byte; State: Boolean);
17+begin
18+ Value := (Value and ((QWord(1) shl Index) xor High(QWord))) or (QWord(State) shl Index);
19+end;
20+
21+function GetBit(Value: QWord; Index: Byte): Boolean;
22+begin
23+ Result := ((Value shr Index) and 1) = 1;
24+end;
25+```
26+
27+## Bitpacked record
28+
29+FPC has useful extension which allow not only byte packing but also bit packing of records. This allow not only to define bit structures using Boolean type or subrange type 0..1 but also n-state or n-bits fields in record, e.g. subrange type 0..3 for 2 bits. This conjunction with record case construction combined structure can be defined which allow to access memory as byte or as individual bits.
30+
31+``` pascal
32+TByteBits = bitpacked record
33+ Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7: Boolean;
34+end;
35+
36+TByteEx = packed record
37+ case Integer of
38+ 0: (ByteAccess: Byte);
39+ 1: (BitAccess: TByteBits);
40+end;
41+
42+TSomeBitLevelStructure = bitpacked record
43+ OneBit: 0..1;
44+ TwoBits: 0..3;
45+ FourBits: 0..15;
46+ EightBits: 0..255
47+end;
48+```
49+
50+Bitpacking can be controlled using compiler directive [\$BITPACKING](http://www.freepascal.org/docs-html/prog/progsu6.html)
51+
52+## Set
53+
54+Because sets are basically an array of all states which is of boolean type, then set can be also used as bit array. But it requires use of [\$PACKSET](http://www.freepascal.org/docs-html/prog/progsu61.html) and [\$PACKENUM](http://www.freepascal.org/docs-html/prog/progsu59.html) compiler directives to change set size. It has also some limitations on max size of set.
55+
56+``` pascal
57+{$packset 1}
58+{$packenum 1}
59+
60+type
61+ TByteBits = set of (Bit0, Bit1, Bit2, Bit3, Bit4, Bit5, Bit6, Bit7);
62+```
63+
64+## TBits
65+
66+This class is part of FPC RTL library contained in Classes unit and has a similar use as in Delphi. It provides only some basic methods for bit manipulation.
67+
68+``` pascal
69+ TBits = class(TObject)
70+ public
71+ constructor Create(TheSize : longint = 0); virtual;
72+ destructor Destroy; override;
73+ function GetFSize : longint;
74+ procedure SetOn(Bit : longint);
75+ procedure Clear(Bit : longint);
76+ procedure Clearall;
77+ procedure AndBits(BitSet : TBits);
78+ procedure OrBits(BitSet : TBits);
79+ procedure XorBits(BitSet : TBits);
80+ procedure NotBits(BitSet : TBits);
81+ function Get(Bit : longint) : boolean;
82+ procedure Grow(NBit : longint);
83+ function Equals(Obj : TObject): Boolean; override; overload;
84+ function Equals(BitSet : TBits) : Boolean; overload;
85+ procedure SetIndex(Index : longint);
86+ function FindFirstBit(State : boolean) : longint;
87+ function FindNextBit : longint;
88+ function FindPrevBit : longint;
89+
90+ { functions and properties to match TBits class }
91+ function OpenBit: longint;
92+ property Bits[Bit: longint]: Boolean read get write SetBit; default;
93+ property Size: longint read FBSize write setSize;
94+ end;
95+```
96+
97+## Record property and value index
98+
99+Another interesting implementation of bit aligned structure can be used with capabilities of advanced records (FPC 2.6.0+). For all properties you have to use setter and getter which can handle general bit manipulations and set index which is passed to these methods. For more information refer to [Indexed properties](http://www.freepascal.org/docs-html/ref/refsu31.html). Because index is only one, it has to be divided to two parameters to describe location and size on bit value. In case of the following example, the offset can be 0..255 and size of value 0..255 bits. Another problem is that you have to ensure that defined structure components will not overlay.
100+
101+``` pascal
102+{$mode delphi}
103+
104+ TSomeBitStructure = record
105+ private
106+ RawData: Word;
107+ function GetBits(const AIndex: Integer): Integer; inline;
108+ procedure SetBits(const AIndex: Integer; const AValue: Integer); inline;
109+ public
110+ // High byte of index offset, low byte of index is bit count
111+ property OneBit: Integer index $0001 read GetBits write SetBits;
112+ property TwoBits: Integer index $0102 read GetBits write SetBits;
113+ property FourBits: Integer index $0304 read GetBits write SetBits;
114+ property EightBits: Integer index $0708 read GetBits write SetBits;
115+ end;
116+
117+{$OPTIMIZATION ON}
118+{$OVERFLOWCHECKS OFF}
119+function TSomeBitStructure.GetBits(const AIndex: Integer): Integer;
120+var
121+ Offset: Integer;
122+ BitCount: Integer;
123+ Mask: Integer;
124+begin
125+ BitCount := AIndex and $FF;
126+ Offset := AIndex shr 8;
127+ Mask := ((1 shl BitCount) - 1);
128+ Result := (RawData shr Offset) and Mask;
129+end;
130+
131+procedure TSomeBitStructure.SetBits(const AIndex: Integer; const AValue: Integer);
132+var
133+ Offset: Integer;
134+ BitCount: Integer;
135+ Mask: Integer;
136+begin
137+ BitCount := AIndex and $FF;
138+ Offset := AIndex shr 8;
139+ Mask := ((1 shl BitCount) - 1);
140+ Assert(aValue <= Mask);
141+ RawData := (RawData and (not (Mask shl Offset))) or (AValue shl Offset);
142+end;
143+```
144+
145+---
146+*From the Free Pascal wiki, page "Bit manipulation", as it stood on 2020-02-07 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
147+Category: Code Snippets
148+Category: FPC
149+Category: Tutorials

Back to history