Forum > Third party
BitHelpers - bit manipulation for standard pascal types
avra:
BitHelpers
BitHelpers 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.
History
FreePascal 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.
Installation
While 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.
Usage
[*]TBooleanBitHelper example code and it's output: [/list]
--- Code: --- uses
bithelpers;
...
procedure TForm1.BooleanBitTestBtnClick(Sender: TObject);
var
MyBool: boolean;
begin
MyBool := true;
Memo1.Append(MyBool.ToOneZeroString);
Memo1.Append(MyBool.ToOnOffString); // default is scfUnchangedCase and can be ommited
Memo1.Append(MyBool.ToOnOffString(scfLowerCase));
Memo1.Append(MyBool.ToTrueFalseString(scfUpperCase));
Memo1.Append(MyBool.ToString('OnState', 'OffState')); // true/false custom strings
Memo1.Append(MyBool.ToString('Укључено', 'Искључено', scfUpperCase)); // when case and unicode matter
end;
--- End code ---
--- Code: --- 1
On
on
TRUE
OnState
УКЉУЧЕНО
--- End code ---
[*]TByteBitHelper example code and it's output: [/list]
--- Code: --- procedure TForm1.ByteBitTestBtnClick(Sender: TObject);
var
MyByte: byte;
begin
MyByte.Clear; // %00000000 MyByte equals 0
MyByte.Bit[0] := true; // %00000001 MyByte equals 1
MyByte.Bit[2] := true; // %00000101 MyByte equals 5
Memo1.Append(MyByte.ToString);
Memo1.Append('$' + MyByte.ToHexString);
Memo1.Append(MyByte.ToBooleanString(lzHideLeadingZeros)); // hide leading zeros
Memo1.Append(MyByte.ToBooleanString); // show leading zeros
end;
--- End code ---
--- Code: --- 5
$05
101
00000101
--- End code ---
[*]TWordBitHelper example code and it's output:[/list]
--- Code: --- procedure TForm1.WordBitTestBtnClick(Sender: TObject);
var
MyWord: word;
begin
MyWord.Clear; // %0000000000000000 MyWord equals 0
MyWord.Byte[0] := 2; // %0000000000000010 MyWord equals 2
MyWord.Byte[1] := 1; // %0000000100000010 MyWord equals 258 (2 + 256)
MyWord.Byte[1].Bit[7] := true; // %0000000100000010 MyWord equals 258 (Beware!!! This DOES NOT set a bit in MyWord !!!)
MyWord.Bit[10] := true; // %0000010100000010 MyWord equals 1282 (258 + 2^10)
Memo1.Append(MyWord.ToString);
Memo1.Append('$' + MyWord.ToHexString);
Memo1.Append(MyWord.ToBooleanString(lzHideLeadingZeros)); // hide leading zeros
Memo1.Append(MyWord.ToBooleanString); // show leading zeros
end;
--- End code ---
--- Code: --- 1282
$0502
10100000010
0000010100000010
--- End code ---
[*]TLongwordBitHelper example code and it's output:[/list]
--- Code: --- procedure TForm1.LongwordBitTestBtnClick(Sender: TObject);
var
MyLongword: longword;
begin
MyLongword.Clear; // %00000000000000000000000000000000 MyLongword equals 0
MyLongword.Word[0] := 250; // %00000000000000000000000011111010 MyLongword equals 250
MyLongword.Word[1].Byte[0] := 100; // %00000000000000000000000011111010 MyLongword equals 250 (Beware!!! This DOES NOT set a byte in MyLongword !!!)
MyLongword.Byte[1] := 4; // %00000000000000000000010011111010 MyLongword equals 1274 (250 + 2^(8 + 2), 2^2 = 4)
MyLongword.Bit[26] := true; // %00000100000000000000010011111010 MyLongword equals 67110138 (1274 + 2^26)
Memo1.Append(MyLongword.ToString);
Memo1.Append('$' + MyLongword.ToHexString);
Memo1.Append(MyLongword.ToBooleanString(lzHideLeadingZeros)); // hide leading zeros
Memo1.Append(MyLongword.ToBooleanString); // show leading zeros
Memo1.Append('');
end;
--- End code ---
--- Code: --- 67110138
$040004FA
100000000000000010011111010
00000100000000000000010011111010
--- End code ---
[*]TQuadwordBitHelper example code and it's output:[/list]
--- Code: --- procedure TForm1.QuadwordBitTestBtnClick(Sender: TObject);
var
MyQuadword: qword;
begin
MyQuadword.Clear; // %0000000000000000000000000000000000000000000000000000000000000000 MyQuadword equals 0
MyQuadword.Longword[0] := 12345; // %0000000000000000000000000000000000000000000000000011000000111001 MyQuadword equals 12345
MyQuadword.Longword[1].Word[0] := 100; // %0000000000000000000000000000000000000000000000000011000000111001 MyQuadword equals 12345 (Beware!!! This DOES NOT set a word in MyQuadword !!!)
MyQuadword.Byte[3] := 2; // %0000000000000000000000000000000000000010000000000011000000111001 MyQuadword equals 33566777 (12345 + 2^(8 + 8 + 8 + 2), 2^1 = 2)
MyQuadword.Bit[50] := true; // %0000000000000100000000000000000000000010000000000011000000111001 MyQuadword equals 1125899940409401 (33566777 + 2^50)
Memo1.Append(MyQuadword.ToString);
Memo1.Append('$' + MyQuadword.ToHexString);
Memo1.Append(MyQuadword.ToBooleanString(lzHideLeadingZeros)); // hide leading zeros
Memo1.Append(MyQuadword.ToBooleanString); // show leading zeros
end;
--- End code ---
--- Code: --- 1125899940409401
$0004000002003039
100000000000000000000000010000000000011000000111001
0000000000000100000000000000000000000010000000000011000000111001
--- End code ---
[*]TQuadwordOverlay, TLongwordOverlay, TWordOverlay and TByteOverlay variant 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:[/list]
--- Code: --- procedure TForm1.OverlaysTestBtnClick(Sender: TObject);
var
MyQuadOverlay: TQuadwordOverlay;
begin
MyQuadOverlay.AsQuadword.Clear;
MyQuadOverlay.AsByte[0] := 100;
Memo1.Append(MyQuadOverlay.AsQuadword.ToBooleanString);
MyQuadOverlay.AsLongword[1] := 1;
Memo1.Append(MyQuadOverlay.AsQuadword.ToBooleanString);
MyQuadOverlay.AsQuadword.Bit[32] := false;
Memo1.Append(MyQuadOverlay.AsQuadword.ToBooleanString);
MyQuadOverlay.AsWordOverlay[3].AsByte[1] := $FF; // recursive overlays are allowed
Memo1.Append(MyQuadOverlay.AsQuadword.ToBooleanString);
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
Memo1.Append(MyQuadOverlay.AsQuadword.ToBooleanString);
MyQuadOverlay.AsBit[63] := false;
Memo1.Append(MyQuadOverlay.AsQuadword.ToBooleanString);
end;
--- End code ---
--- Code: --- 0000000000000000000000000000000000000000000000000000000001100100
0000000000000000000000000000000100000000000000000000000001100100
0000000000000000000000000000000000000000000000000000000001100100
1111111100000000000000000000000000000000000000000000000001100100
1111111100000000000000000000000000000000000000000000000001100100
0111111100000000000000000000000000000000000000000000000001100100
--- End code ---
Download
https://bitbucket.org/avra/bithelpers
License
BitHelpers package is released under triple license:
* LGPLv3 - chosen for compatibility with Pasettimino. License explained in plain english.
* FPC modified LGPL - chosen for compatibility with FreePascal and Lazarus.
* BSD3 - chosen for compatibility with everything else. License explained in plain english.
garlar27:
Hi Avra!!
Good job!!!
It's a shame not knowing about it 5-7 years ago, it would saved me a lot of time and I would be using it for sure!!!
The only cons I see from the examples (I haven't downloaded the package and didn't checked the full capacity either) is the lack of configurable separators for nibbles and bytes in the ToBooleanString function; and configurable separators for each byte and "n" bytes in the ToHexString function. I need those to ease the logs readability. For instance:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---11.24.03.019 - Rx-<STX><$97><NUL><NUL><FS><$C0><$81><FS>11.24.03.028 - Rx-<FS><NUL><NUL><FS><ETX>02411.24.03.037 - Rx-D11.24.03.046 - Tx-<ACK>11.24.03.055 - // ### Received: 02 97 00 00 1C C0 81 1C 1C 00 00 1C 03 30 32 34 4411.24.03.083 - // ### Status 1: hex( 00 00); bin( 00000000 00000000)11.24.03.091 - // ### Status 2: hex( C0 81); bin( 11000000 10000001)11.24.03.268 - // ### command PrnTK_TKNC_Item() // Extension [ bin: 00000000 00110000; Hex: 00 30]:11.24.03.287 - // ### string to send: 02 98 0A 1B 02 1C 00 30 1C 1C 1C 1C 1C 53 61 6C 61 6D 65 20 4D 69 6C 61 6E 20 70 69 65 7A 61 1C 31 30 30 30 30 1C 39 30 30 30 30 30 1C 32 31 30 30 1C 1C 1C 1C 1C 37 39 30 31 1C 30 30 1C 37 03 30 44 39 3611.24.03.300 - Tx-<STX><$98><LF><ESC><STX><FS><NUL>0<FS><FS><FS><FS><FS>Salame Milan pieza<FS>10000<FS>900000<FS>2100<FS><FS><FS><FS><FS>7901<FS>00<FS>7<ETX>0D96
Other thing I needed back then was encoding numbers in a BCD string with a predetermined "endianness" (which could be the same or different from the host PC) and send them to a server. What I did was not optimal but it worked :-[ .
I also had problem to get the raw value of a number as i t is in memory to a string (for instance: a Byte = 65 converted to string should be "A" if I need it in LE).
It is not a formal feature request since I think I'm not going to use such features in the near future. And I don't know if such things are already implemented.
I used such things to communicate with hardware such like VeriFone PINPads and fiscal printers like Hasar and Epson. Also to communicate with VISA servers (that project was halted or in stand by just before try to comply with IPC standard).-
Thaddy:
--- Quote from: garlar27 on September 27, 2018, 05:02:33 pm ---Hi Avra!!
Good job!!!
It's a shame not knowing about it 5-7 years ago, it would saved me a lot of time and I would be using it for sure!!!
--- End quote ---
Five to seven years ago this would not be possible with this syntax..
lucamar:
Very nice. But ... something of a misname, ToBooleanString, isn't it? Shouldn't have been p.e. ToBinaryString? Or I may be missing something, of course :D
garlar27:
--- Quote from: lucamar on September 27, 2018, 05:57:48 pm ---Very nice. But ... something of a misname, ToBooleanString, isn't it? Shouldn't have been p.e. ToBinaryString? Or I may be missing something, of course :D
--- End quote ---
I agree, but I think people who knows or usually work with assembler might not think the same.
Navigation
[0] Message Index
[#] Next page