Sign in Join
Wiki copytemporary

BitHelpers: what changed

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

OldNewLine
11# About
22
33BitHelpers enable additional bit manipulation for qword, longword, word, byte and boolean types which will make your life much easier if you need such a feature.
44
55Homepage: <https://bitbucket.org/avra/bithelpers>
66
77FreePascal type helpers TBooleanHelper, TByteHelper, TWordHelper, TCardinalHelper and TQWordHelper do not offer much when bit manipulation and presentation are needed. That's where BitHelpers package jumps in, nicely extending mentioned type helpers.
88
99IMPORTANT NEWS: I am so glad to announce that BitHelpers are now part of trunk FreePascal RTL. Type helpers for direct access to bit, nibble, byte, word and dword parts in ordinal types are now part of sysutils unit, and customizable boolean, binary and hexadecimal data localized string representation is now part of syshelpers unit. Syntax has been slightly changed to be more in line with FreePascal (using plurals like SomeOrdType.Bits\[3\] instead of old SomeOrdType.Bit\[3\] and similar). More details at <https://gitlab.com/freepascal.org/fpc/source/-/issues/39268> and <https://gitlab.com/freepascal.org/fpc/documentation/-/issues/39267>. From now on, all further development will be in FreePascal trunk. Bitbucket repo will continue to exist only for historical reasons and old code.
1010
1111# Installation
1212
1313While you can simply copy bithelpers unit to your project directory and start using it, the recommended way would be to open "bithelpers_pkg.lpk" package and compile it. That would add BitHelpers source directory to Lazarus and make it available to all your projects.
1414
1515# Usage
1616
1717## TBooleanBitHelper
1818
1919Example code and it's output:
2020
2121``` pascal
2222 uses
2323 bithelpers;
2424 ...
2525 procedure TForm1.BooleanBitTestBtnClick(Sender: TObject);
2626 var
2727 MyBool: boolean;
2828 begin
2929 MyBool := true;
3030 Memo1.Append(MyBool.ToOneZeroString);
3131 Memo1.Append(MyBool.ToOnOffString); // default is scfUnchangedCase and can be ommited
3232 Memo1.Append(MyBool.ToOnOffString(scfLowerCase));
3333 Memo1.Append(MyBool.ToTrueFalseString(scfUpperCase));
3434 Memo1.Append(MyBool.ToString('OnState', 'OffState')); // true/false custom strings
3535 Memo1.Append(MyBool.ToString('Укључено', 'Искључено', scfUpperCase)); // when case and unicode matter
3636 end;
3737```
3838
39-`  1`\
40-`  On`\
41-`  on`\
42-`  TRUE`\
43-`  OnState`\
44-`  УКЉУЧЕНО`
39+```
40+ 1
41+ On
42+ on
43+ TRUE
44+ OnState
45+ УКЉУЧЕНО
46+```
4547
4648## TByteBitHelper
4749
4850Example code and it's output:
4951
5052``` pascal
5153 procedure TForm1.ByteBitTestBtnClick(Sender: TObject);
5254 var
5355 MyByte: byte;
5456 begin
5557 MyByte.Clear; // %00000000 MyByte equals 0
5658 MyByte.Bit[0] := true; // %00000001 MyByte equals 1
5759 MyByte.Bit[2] := true; // %00000101 MyByte equals 5
5860 Memo1.Append(MyByte.ToString);
5961 Memo1.Append('$' + MyByte.ToHexString);
6062 Memo1.Append(MyByte.ToBinString(lzHideLeadingZeros)); // hide leading zeros
6163 Memo1.Append(MyByte.ToBinString); // show leading zeros
6264 end;
6365```
6466
65-`  5`\
66-`  $05`\
67-`  101`\
68-`  00000101`
67+```
68+ 5
69+ $05
70+ 101
71+ 00000101
72+```
6973
7074## TWordBitHelper
7175
7276Example code and it's output:
7377
7478``` pascal
7579 procedure TForm1.WordBitTestBtnClick(Sender: TObject);
7680 var
7781 MyWord: word;
7882 begin
7983 MyWord.Clear; // %0000000000000000 MyWord equals 0
8084 MyWord.Byte[0] := 2; // %0000000000000010 MyWord equals 2
8185 MyWord.Byte[1] := 1; // %0000000100000010 MyWord equals 258 (2 + 256)
8286 MyWord.Byte[1].Bit[7] := true; // %0000000100000010 MyWord equals 258 (Beware!!! This DOES NOT set a bit in MyWord !!!)
8387 MyWord.Bit[10] := true; // %0000010100000010 MyWord equals 1282 (258 + 2^10)
8488 Memo1.Append(MyWord.ToString);
8589 Memo1.Append('$' + MyWord.ToHexString);
8690 Memo1.Append(MyWord.ToBinString(lzHideLeadingZeros)); // hide leading zeros
8791 Memo1.Append(MyWord.ToBinString); // show leading zeros
8892 end;
8993```
9094
91-`  1282`\
92-`  $0502`\
93-`  10100000010`\
94-`  0000010100000010`
95+```
96+ 1282
97+ $0502
98+ 10100000010
99+ 0000010100000010
100+```
95101
96102## TLongwordBitHelper
97103
98104Example code and it's output:
99105
100106``` pascal
101107 procedure TForm1.LongwordBitTestBtnClick(Sender: TObject);
102108 var
103109 MyLongword: longword;
104110 begin
105111 MyLongword.Clear; // %00000000000000000000000000000000 MyLongword equals 0
106112 MyLongword.Word[0] := 250; // %00000000000000000000000011111010 MyLongword equals 250
107113 MyLongword.Word[1].Byte[0] := 100; // %00000000000000000000000011111010 MyLongword equals 250 (Beware!!! This DOES NOT set a byte in MyLongword !!!)
108114 MyLongword.Byte[1] := 4; // %00000000000000000000010011111010 MyLongword equals 1274 (250 + 2^(8 + 2), 2^2 = 4)
109115 MyLongword.Bit[26] := true; // %00000100000000000000010011111010 MyLongword equals 67110138 (1274 + 2^26)
110116 Memo1.Append(MyLongword.ToString);
111117 Memo1.Append('$' + MyLongword.ToHexString);
112118 Memo1.Append(MyLongword.ToBinString(lzHideLeadingZeros)); // hide leading zeros
113119 Memo1.Append(MyLongword.ToBinString); // show leading zeros
114120 Memo1.Append('');
115121 end;
116122```
117123
118-`  67110138`\
119-`  $040004FA`\
120-`  100000000000000010011111010`\
121-`  00000100000000000000010011111010`
124+```
125+ 67110138
126+ $040004FA
127+ 100000000000000010011111010
128+ 00000100000000000000010011111010
129+```
122130
123131## TQuadwordBitHelper
124132
125133Example code and it's output:
126134
127135``` pascal
128136 procedure TForm1.QuadwordBitTestBtnClick(Sender: TObject);
129137 var
130138 MyQuadword: qword;
131139 begin
132140 MyQuadword.Clear; // %0000000000000000000000000000000000000000000000000000000000000000 MyQuadword equals 0
133141 MyQuadword.Longword[0] := 12345; // %0000000000000000000000000000000000000000000000000011000000111001 MyQuadword equals 12345
134142 MyQuadword.Longword[1].Word[0] := 100; // %0000000000000000000000000000000000000000000000000011000000111001 MyQuadword equals 12345 (Beware!!! This DOES NOT set a word in MyQuadword !!!)
135143 MyQuadword.Byte[3] := 2; // %0000000000000000000000000000000000000010000000000011000000111001 MyQuadword equals 33566777 (12345 + 2^(8 + 8 + 8 + 2), 2^1 = 2)
136144 MyQuadword.Bit[50] := true; // %0000000000000100000000000000000000000010000000000011000000111001 MyQuadword equals 1125899940409401 (33566777 + 2^50)
137145 Memo1.Append(MyQuadword.ToString);
138146 Memo1.Append('$' + MyQuadword.ToHexString);
139147 Memo1.Append(MyQuadword.ToBinString(lzHideLeadingZeros)); // hide leading zeros
140148 Memo1.Append(MyQuadword.ToBinString); // show leading zeros
141149 end;
142150```
143151
144-`  1125899940409401`\
145-`  $0004000002003039`\
146-`  100000000000000000000000010000000000011000000111001`\
147-`  0000000000000100000000000000000000000010000000000011000000111001`
152+```
153+ 1125899940409401
154+ $0004000002003039
155+ 100000000000000000000000010000000000011000000111001
156+ 0000000000000100000000000000000000000010000000000011000000111001
157+```
148158
149159## TQuadwordOverlay, TLongwordOverlay, TWordOverlay and TByteOverlay
150160
151161Variant records are also provided for qword, longword, word and byte. Sometimes they are more convenient to use then type helpers, and nothing stops you to mix them when needed. Here is an example code and it's output:
152162
153163``` pascal
154164 procedure TForm1.OverlaysTestBtnClick(Sender: TObject);
155165 var
156166 MyQuadOverlay: TQuadwordOverlay;
157167 begin
158168 MyQuadOverlay.AsQuadword.Clear;
159169 MyQuadOverlay.AsByte[0] := 100;
160170 Memo1.Append(MyQuadOverlay.AsQuadword.ToBinString);
161171 MyQuadOverlay.AsLongword[1] := 1;
162172 Memo1.Append(MyQuadOverlay.AsQuadword.ToBinString);
163173 MyQuadOverlay.AsQuadword.Bit[32] := false;
164174 Memo1.Append(MyQuadOverlay.AsQuadword.ToBinString);
165175 MyQuadOverlay.AsWordOverlay[3].AsByte[1] := $FF; // recursive overlays are allowed
166176 Memo1.Append(MyQuadOverlay.AsQuadword.ToBinString);
167177 MyQuadOverlay.AsWord[3].Byte[1].Bit[5] := false; // NO CHANGE !!! Bit is set in a result byte, not in a byte that belongs to MyQuadOverlay
168178 Memo1.Append(MyQuadOverlay.AsQuadword.ToBinString);
169179 MyQuadOverlay.AsBit[63] := false;
170180 Memo1.Append(MyQuadOverlay.AsQuadword.ToBinString);
171181 end;
172182```
173183
174-`  0000000000000000000000000000000000000000000000000000000001100100`\
175-`  0000000000000000000000000000000100000000000000000000000001100100`\
176-`  0000000000000000000000000000000000000000000000000000000001100100`\
177-`  1111111100000000000000000000000000000000000000000000000001100100`\
178-`  1111111100000000000000000000000000000000000000000000000001100100`\
179-`  0111111100000000000000000000000000000000000000000000000001100100`
184+```
185+ 0000000000000000000000000000000000000000000000000000000001100100
186+ 0000000000000000000000000000000100000000000000000000000001100100
187+ 0000000000000000000000000000000000000000000000000000000001100100
188+ 1111111100000000000000000000000000000000000000000000000001100100
189+ 1111111100000000000000000000000000000000000000000000000001100100
190+ 0111111100000000000000000000000000000000000000000000000001100100
191+```
180192
181193## HighestBitPos(), LowestBitPos() and BitsCount()
182194
183195HighestBitPos(), LowestBitPos() and BitsCount() are used for getting position of left most bit, right most bit, and number of set bits. Beware that for a value of 0, result of HighestBitPos() and LowestBitPos() will be 255 (unsigned equivalent of -1). Here is an example code and it's output:
184196
185197``` pascal
186198 procedure TForm1.BitsPosAndCountClick(Sender: TObject);
187199 var
188200 MyQuadWord: qword;
189201 begin
190202 MyQuadWord := $7F00000000000064; // 0111111100000000000000000000000000000000000000000000000001100100
191203 Memo1.Append(MyQuadword.ToBinString);
192204 Memo1.Append('MyQuadword.HighestBitPos = ' + MyQuadword.HighestBitPos.ToString);
193205 Memo1.Append('MyQuadword.LowestBitPos = ' + MyQuadword.LowestBitPos.ToString);
194206 Memo1.Append('MyQuadword.BitsCount = ' + MyQuadword.BitsCount.ToString);
195207 Memo1.Append('');
196208 end;
197209```
198210
199-` 0111111100000000000000000000000000000000000000000000000001100100`\
200-` MyQuadword.HighestBitPos = 62`\
201-` MyQuadword.LowestBitPos = 2`\
202-` MyQuadword.BitsCount = 10`
211+```
212+ 0111111100000000000000000000000000000000000000000000000001100100
213+ MyQuadword.HighestBitPos = 62
214+ MyQuadword.LowestBitPos = 2
215+ MyQuadword.BitsCount = 10
216+```
203217
204218## ToBinString custom formatting
205219
206220ToBinString() can follow custom formatting when needed. Binary string output can be changed permanently by modifying fields of DefaultHelperFormatSettings global record, or temporary by creating a record of THelperFormatSettings type, populating it's fields and making it as a parameter of ToBinString(). It will be more clear in following examples - first how to use temporary format:
207221
208222``` pascal
209223 procedure TForm1.TmpFormatBtnClick(Sender: TObject);
210224 var
211225 MyQuadWord: qword;
212226 MyTmpFormat: THelperFormatSettings;
213227 begin
214228 MyQuadWord := 1125899940409401;
215229
216230 MyTmpFormat.PrefixString := '< ';
217231 MyTmpFormat.SufixString := ' >';
218232 MyTmpFormat.ByteSeparator := ' - ';
219233 MyTmpFormat.WordSeparator := ' = ';
220234 MyTmpFormat.LongwordSeparator := ' ';
221235 MyTmpFormat.NibbleSeparator := '.';
222236
223237 Memo1.Append('MyQuadword.ToBinString(MyTmpFormat, true);');
224238 Memo1.Append(MyQuadword.ToBinString(MyTmpFormat, true)); // true is default so it can be ommited and leading zeros will still be shown
225239 Memo1.Append('MyQuadword.Longword[1].ToBinString(MyTmpFormat);');
226240 Memo1.Append(MyQuadword.Longword[1].ToBinString(MyTmpFormat)); // default true is ommited, show higher longword with leading zeros
227241 Memo1.Append('MyQuadword.Word[3].ToBinString(MyTmpFormat, false);');
228242 Memo1.Append(MyQuadword.Word[3].ToBinString(MyTmpFormat, false)); // show highest word without leading zeros
229243 end;
230244```
231245
232-`  MyQuadword.ToBinString(MyTmpFormat, true);`\
233-`  < 0000.0000 - 0000.0100 = 0000.0000 - 0000.0000   0000.0010 - 0000.0000 = 0011.0000 - 0011.1001 >`\
234-`  MyQuadword.Longword[1].ToBinString(MyTmpFormat);`\
235-`  < 0000.0000 - 0000.0100 = 0000.0000 - 0000.0000 >`\
236-`  MyQuadword.Word[3].ToBinString(MyTmpFormat, false);`\
237-`  < 100 >`
246+```
247+ MyQuadword.ToBinString(MyTmpFormat, true);
248+ < 0000.0000 - 0000.0100 = 0000.0000 - 0000.0000 0000.0010 - 0000.0000 = 0011.0000 - 0011.1001 >
249+ MyQuadword.Longword[1].ToBinString(MyTmpFormat);
250+ < 0000.0000 - 0000.0100 = 0000.0000 - 0000.0000 >
251+ MyQuadword.Word[3].ToBinString(MyTmpFormat, false);
252+ < 100 >
253+```
238254
239255and then permanent format example:
240256
241257``` pascal
242258 procedure TForm1.ChangeFormatBtnClick(Sender: TObject);
243259 var
244260 MyQuadWord: qword;
245261 begin
246262 MyQuadWord := 1125899940409401;
247263
248264 // all DefaultHelperFormatSettings fields are empty strings by default, so we change them here:
249265 DefaultHelperFormatSettings.PrefixString := '{';
250266 DefaultHelperFormatSettings.SufixString := '}';
251267 DefaultHelperFormatSettings.NibbleSeparator := '_';
252268 DefaultHelperFormatSettings.ByteSeparator := ' ';
253269 DefaultHelperFormatSettings.WordSeparator := ' ' + Chr(39) + ' '; // single quote
254270 DefaultHelperFormatSettings.LongwordSeparator := ' " ';
255271
256272 Memo1.Append(MyQuadword.ToBinString(true));
257273 Memo1.Append(MyQuadword.Longword[1].ToBinString);
258274 Memo1.Append(MyQuadword.Word[3].ToBinString(false));
259275 end;
260276```
261277
262-`  {0000_0000  0000_0100  '  0000_0000  0000_0000  "  0000_0010  0000_0000  '  0011_0000  0011_1001}`\
263-`  {0000_0000  0000_0100  '  0000_0000  0000_0000}`\
264-`  {100}`
278+```
279+ {0000_0000 0000_0100 ' 0000_0000 0000_0000 " 0000_0010 0000_0000 ' 0011_0000 0011_1001}
280+ {0000_0000 0000_0100 ' 0000_0000 0000_0000}
281+ {100}
282+```
265283
266284# License
267285
268286BitHelpers package is released under triple license:
269287
270288- [[https://www.gnu.org/licenses/lgpl-3.0.en.html LGPLv3]] - chosen for compatibility with Pasettimino.
271289- [[http://wiki.freepascal.org/FPC modified LGPL FPC modified LGPL]] - chosen for compatibility with FreePascal and Lazarus.
272290- [[https://opensource.org/licenses/BSD-3-Clause BSD3]] - chosen for compatibility with everything else.
273291
274292---
275293*From the Free Pascal wiki, page "BitHelpers", as it stood on 2022-01-19 after a change by Avra, 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).*

Back to history