Subversion Repositories delphiutils

Rev

Rev 12 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit BitOps;
  2.  
  3. (*************************************************************
  4.  
  5.     BitOps.pas
  6.     Bit- Byte- and Nibbleoperations
  7.     64 Bit Edition; Rev 05 July 2010
  8.  
  9.     (C) 2010 ViaThinkSoft [www.viathinksoft.com]
  10.     Developed by Daniel Marschall [www.daniel-marschall.de]
  11.  
  12. *************************************************************)
  13.  
  14. interface
  15.  
  16. uses
  17.   SysUtils;
  18.  
  19. // * TYPES *
  20.  
  21. type
  22.   Nibble = 0..127;
  23.   THexNibble = $0..$F;
  24.   T4BitPos = 0..3;
  25.   T8BitPos = 0..7;
  26.   T16BitPos = 0..15;
  27.   T32BitPos = 0..31;
  28.   T64BitPos = 0..63;
  29.  
  30.   // Maximum amount of bytes in the biggest data type (int64)
  31.   TBytePos = 0..7;
  32.   // Maximum amount of nibbles in the biggest data type (int64)
  33.   THexNibblePos = 0..15;
  34.  
  35.   TBit = Boolean;
  36.   THexNibbleBitArray = array[Low(T4BitPos)..High(T4BitPos)] of TBit;
  37.   TByteBitArray = array[Low(T8BitPos)..High(T8BitPos)] of TBit;
  38.   TBitString = type string;
  39.   TByteBitString = type TBitString;
  40.   THexNibbleBitString = type TBitString;
  41.  
  42. // ******************
  43. // * BYTE FUNCTIONS *
  44. // ******************
  45.  
  46. // Build a byte.
  47. // Either you combine two nibbles...
  48. function BuildByte(AUpperNibble, ALowerNibble: THexNibble): Byte; overload;
  49. // ...or you define an array of 8 bits.
  50. function BuildByte(ABitArray: TByteBitArray): Byte; overload;
  51. // ...or you define a bitstring (e.g. '00011100')
  52. function BuildByte(ABits: TByteBitString): Byte; overload;
  53. // ...or you define the bits as parameters
  54. function BuildByte(ABit1, ABit2, ABit3, ABit4, ABit5, ABit6, ABit7,
  55.   ABit8: TBit): Byte; overload;
  56.  
  57. // Converts a byte into a array of 8 bits
  58. function GetByteBitArray(AByte: Byte): TByteBitArray;
  59.  
  60. // Getting and setting the lower nibble of a byte.
  61. function GetLowerNibble(AByte: Byte): THexNibble;
  62. function SetLowerNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
  63.  
  64. // Getting and setting the upper nibble of a byte.
  65. function GetUpperNibble(AByte: Byte): THexNibble;
  66. function SetUpperNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
  67.  
  68. // Interchanges upper and lower Nibble in a byte
  69. function InterchangeNibbles(AByte: Byte): Byte;
  70.  
  71. // Creates an 8-bit-array from a 8-bit-string
  72. // Throws EBitStringTooLong and EBitStringInvalidCharacter
  73. function ByteBitArrayFromBitString(const ABits: TByteBitString):
  74.   TByteBitArray;
  75.  
  76. // Getting and setting of a bit in a byte
  77. function GetByteBit(AByte: Byte; ABitPos: T8BitPos): TBit;
  78. function SetByteBit(AByte: Byte; ABitPos: T8BitPos; ANewBit: TBit): Byte;
  79.  
  80. // Getting and setting of a bit in a AnsiChar
  81. function GetAnsiCharBit(AChar: AnsiChar; ABitPos: T8BitPos): TBit;
  82. function SetAnsiCharBit(AChar: AnsiChar; ABitPos: T8BitPos; ANewBit: TBit): Byte;
  83.  
  84. // Logical operations for the 8 bit arrays.
  85. function ByteBitArrayShr(ABitArray: TByteBitArray;
  86.   AVal: Longword): TByteBitArray;
  87. function ByteBitArrayShl(ABitArray: TByteBitArray;
  88.   AVal: Longword): TByteBitArray;
  89. function ByteBitArrayAnd(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
  90. function ByteBitArrayOr(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
  91. function ByteBitArrayXor(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
  92. function ByteBitArrayNot(ABitArray: TByteBitArray): TByteBitArray;
  93.  
  94. // Inverse the bits of a byte
  95. function InverseByteBits(x: Byte): Byte;
  96.  
  97. // Reverses the bit sequence of a byte
  98. function ReverseByteBitSequence(AByte: Byte): Byte;
  99.  
  100. // ********************
  101. // * NIBBLE FUNCTIONS *
  102. // ********************
  103.  
  104. // Build a Nibble.
  105. // You can define an array of 4 bits.
  106. function BuildNibble(ABitArray: THexNibbleBitArray): Nibble; overload;
  107. // ...or you define a bitstring (e.g. '0001')
  108. function BuildNibble(ABits: THexNibbleBitString): Nibble; overload;
  109. // ...or you define the bits as parameters
  110. function BuildNibble(ABit1, ABit2, ABit3, ABit4: TBit): Nibble; overload;
  111.  
  112. // Converts a nibble into a array of 4 bits
  113. function GetNibbleBitArray(ANibble: Nibble): THexNibbleBitArray;
  114.  
  115. // Creates an 4-bit-array from a 4-bit-string
  116. // Throws EBitStringTooLong and EBitStringInvalidCharacter
  117. function NibbleBitArrayFromBitString(const ABits: THexNibbleBitString):
  118.   THexNibbleBitArray;
  119.  
  120. // Getting and setting of a bit in a nibble
  121. function GetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos): TBit;
  122. function SetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos;
  123.   ANewBit: TBit): Nibble;
  124.  
  125. // Logical operations for the 4 bit arrays.
  126. function NibbleBitArrayShr(ABitArray: THexNibbleBitArray; AVal: Longword):
  127.   THexNibbleBitArray;
  128. function NibbleBitArrayShl(ABitArray: THexNibbleBitArray; AVal: Longword):
  129.   THexNibbleBitArray;
  130. function NibbleBitArrayAnd(ABitArray, ABitArray2: THexNibbleBitArray):
  131.   THexNibbleBitArray;
  132. function NibbleBitArrayOr(ABitArray, ABitArray2: THexNibbleBitArray):
  133.   THexNibbleBitArray;
  134. function NibbleBitArrayXor(ABitArray, ABitArray2: THexNibbleBitArray):
  135.   THexNibbleBitArray;
  136. function NibbleBitArrayNot(ABitArray: THexNibbleBitArray): THexNibbleBitArray;
  137.  
  138. // Inverse the bits of a nibble
  139. function InverseNibbleBits(x: Nibble): Nibble;
  140.  
  141. // Reverses the bit sequence of a nibble
  142. function ReverseNibbleBitSequence(ANibble: Nibble): Nibble;
  143.  
  144. // * EXCEPTIONS *
  145.  
  146. type
  147.   EInvalidBitString = class(Exception);
  148.   EBitStringTooLong = class(EInvalidBitString);
  149.   EBitStringInvalidCharacter = class(EInvalidBitString);
  150.  
  151. // * CONSTANTS *
  152.  
  153. // Lookup tables to avoid calculation each time
  154. const
  155.   AllSetBitsBytes: array[TBytePos] of int64 =
  156.    ($00000000000000FF,
  157.     $000000000000FFFF,
  158.     $0000000000FFFFFF,
  159.     $00000000FFFFFFFF,
  160.     $000000FFFFFFFFFF,
  161.     $0000FFFFFFFFFFFF,
  162.     $00FFFFFFFFFFFFFF,
  163.     $FFFFFFFFFFFFFFFF);
  164.  
  165.   AllSetBitsNibbles: array[THexNibblePos] of int64 =
  166.    ($000000000000000F,
  167.     $00000000000000FF,
  168.     $0000000000000FFF,
  169.     $000000000000FFFF,
  170.     $00000000000FFFFF,
  171.     $0000000000FFFFFF,
  172.     $000000000FFFFFFF,
  173.     $00000000FFFFFFFF,
  174.     $0000000FFFFFFFFF,
  175.     $000000FFFFFFFFFF,
  176.     $00000FFFFFFFFFFF,
  177.     $0000FFFFFFFFFFFF,
  178.     $000FFFFFFFFFFFFF,
  179.     $00FFFFFFFFFFFFFF,
  180.     $0FFFFFFFFFFFFFFF,
  181.     $FFFFFFFFFFFFFFFF);
  182.  
  183.   AllSetBitsNibble: array[THexNibblePos] of int64 =
  184.    ($000000000000000F,
  185.     $00000000000000F0,
  186.     $0000000000000F00,
  187.     $000000000000F000,
  188.     $00000000000F0000,
  189.     $0000000000F00000,
  190.     $000000000F000000,
  191.     $00000000F0000000,
  192.     $0000000F00000000,
  193.     $000000F000000000,
  194.     $00000F0000000000,
  195.     $0000F00000000000,
  196.     $000F000000000000,
  197.     $00F0000000000000,
  198.     $0F00000000000000,
  199.     $F000000000000000);
  200.  
  201.   // Deprecated function:
  202.   // function GetSingleBit(ABit: T64BitPos): Int64;
  203.   //
  204.   // Gives you a 64 bit datatype which is representing the binary coding
  205.   //
  206.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001,
  207.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000010,
  208.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100,
  209.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00001000,
  210.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00010000,
  211.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00100000,
  212.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01000000,
  213.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10000000,
  214.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000000,
  215.   // ...
  216.   // 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000.
  217.   //
  218.   // Limitation because of the data type: 64 Bit
  219.   //
  220.   // For the GetByteBit() and SetByteBit functions we only need this array to
  221.   // be max at $80 (128).
  222.   // Manual calculation (not 64 bit useable) would be
  223.   // result := Math.Floor(Math.Power(2, ABit));
  224.   SingleBitArray: array[T64BitPos] of int64 =
  225.    ($0000000000000001, $0000000000000002, $0000000000000004, $0000000000000008,
  226.     $0000000000000010, $0000000000000020, $0000000000000040, $0000000000000080,
  227.     $0000000000000100, $0000000000000200, $0000000000000400, $0000000000000800,
  228.     $0000000000001000, $0000000000002000, $0000000000004000, $0000000000008000,
  229.     $0000000000010000, $0000000000020000, $0000000000040000, $0000000000080000,
  230.     $0000000000100000, $0000000000200000, $0000000000400000, $0000000000800000,
  231.     $0000000001000000, $0000000002000000, $0000000004000000, $0000000008000000,
  232.     $0000000010000000, $0000000020000000, $0000000040000000, $0000000080000000,
  233.     $0000000100000000, $0000000200000000, $0000000400000000, $0000000800000000,
  234.     $0000001000000000, $0000002000000000, $0000004000000000, $0000008000000000,
  235.     $0000010000000000, $0000020000000000, $0000040000000000, $0000080000000000,
  236.     $0000100000000000, $0000200000000000, $0000400000000000, $0000800000000000,
  237.     $0001000000000000, $0002000000000000, $0004000000000000, $0008000000000000,
  238.     $0010000000000000, $0020000000000000, $0040000000000000, $0080000000000000,
  239.     $0100000000000000, $0200000000000000, $0400000000000000, $0800000000000000,
  240.     $1000000000000000, $2000000000000000, $4000000000000000, $8000000000000000);
  241.  
  242.   // Deprecated function:
  243.   // function GetSingleBitDynamicInversed(ABit: T64BitPos): Int64;
  244.   //
  245.   // Gives you a 64 bit datatype which is representing the dynamic inversed
  246.   // binary encoding. (Dynamic inversed means, that only the used bytes get
  247.   // inverted, so this is NOT the same as "NOT GetSingleBit(ABit)"!)
  248.   //
  249.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11111110,
  250.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11111101,
  251.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11111011,
  252.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11110111,
  253.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11101111,
  254.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11011111,
  255.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10111111,
  256.   // 00000000 00000000 00000000 00000000 00000000 00000000 00000000 01111111,
  257.   // 00000000 00000000 00000000 00000000 00000000 00000000 11111110 11111111,
  258.   // ...
  259.   // 01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111.
  260.   //
  261.   // Limitation because of the data type: 64 Bit
  262.   //
  263.   // Manual calculation (not 64 bit useable) would be
  264.   // result := MathFloor(
  265.   //   Math.Power(256, Math.Floor(ABit / 8)+1)-1 {***} -
  266.   //   Math.Power(2, ABit));
  267.   //
  268.   // *** is the maximal value of the byte amount we were requesting.
  269.   // Example:
  270.   // If ABit in [ 0.. 7] => 1 Byte  used => (256^1-1) = $FF
  271.   // If ABit in [ 8..15] => 2 Bytes used => (256^2-1) = $FF FF
  272.   // If ABit in [16..23] => 3 Bytes used => (256^3-1) = $FF FF FF
  273.   // If ABit in [24..31] => 4 Bytes used => (256^3-1) = $FF FF FF FF
  274.   // ...
  275.   SingleBitArrayDynamicInversed: array[T64BitPos] of int64 =
  276.    ($00000000000000FE, $00000000000000FD, $00000000000000FB, $00000000000000F7,
  277.     $00000000000000EF, $00000000000000DF, $00000000000000BF, $000000000000007F,
  278.     $000000000000FEFF, $000000000000FDFF, $000000000000FBFF, $000000000000F7FF,
  279.     $000000000000EFFF, $000000000000DFFF, $000000000000BFFF, $0000000000007FFF,
  280.     $0000000000FEFFFF, $0000000000FDFFFF, $0000000000FBFFFF, $0000000000F7FFFF,
  281.     $0000000000EFFFFF, $0000000000DFFFFF, $0000000000BFFFFF, $00000000007FFFFF,
  282.     $00000000FEFFFFFF, $00000000FDFFFFFF, $00000000FBFFFFFF, $00000000F7FFFFFF,
  283.     $00000000EFFFFFFF, $00000000DFFFFFFF, $00000000BFFFFFFF, $000000007FFFFFFF,
  284.     $000000FEFFFFFFFF, $000000FDFFFFFFFF, $000000FBFFFFFFFF, $000000F7FFFFFFFF,
  285.     $000000EFFFFFFFFF, $000000DFFFFFFFFF, $000000BFFFFFFFFF, $0000007FFFFFFFFF,
  286.     $0000FEFFFFFFFFFF, $0000FDFFFFFFFFFF, $0000FBFFFFFFFFFF, $0000F7FFFFFFFFFF,
  287.     $0000EFFFFFFFFFFF, $0000DFFFFFFFFFFF, $0000BFFFFFFFFFFF, $00007FFFFFFFFFFF,
  288.     $00FEFFFFFFFFFFFF, $00FDFFFFFFFFFFFF, $00FBFFFFFFFFFFFF, $00F7FFFFFFFFFFFF,
  289.     $00EFFFFFFFFFFFFF, $00DFFFFFFFFFFFFF, $00BFFFFFFFFFFFFF, $007FFFFFFFFFFFFF,
  290.     $FEFFFFFFFFFFFFFF, $FDFFFFFFFFFFFFFF, $FBFFFFFFFFFFFFFF, $F7FFFFFFFFFFFFFF,
  291.     $EFFFFFFFFFFFFFFF, $DFFFFFFFFFFFFFFF, $BFFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF);
  292.  
  293.   // Gives you a 64 bit datatype which is representing the inversed
  294.   // binary encoding.
  295.   //
  296.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111110,
  297.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111101,
  298.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011,
  299.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11110111,
  300.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11101111,
  301.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11011111,
  302.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 10111111,
  303.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111111 01111111,
  304.   // 11111111 11111111 11111111 11111111 11111111 11111111 11111110 11111111,
  305.   // ...
  306.   // 01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111.
  307.   //
  308.   // Limitation because of the data type: 64 Bit
  309.   //
  310.   // Manual calculation (not 64 bit useable) would be
  311.   // result := NOT GetSingleBit(ABit)
  312.   //
  313.   SingleBitArrayInversed: array[T64BitPos] of int64 =
  314.    ($FFFFFFFFFFFFFFFE, $FFFFFFFFFFFFFFFD, $FFFFFFFFFFFFFFFB, $FFFFFFFFFFFFFFF7,
  315.     $FFFFFFFFFFFFFFEF, $FFFFFFFFFFFFFFDF, $FFFFFFFFFFFFFFBF, $FFFFFFFFFFFFFF7F,
  316.     $FFFFFFFFFFFFFEFF, $FFFFFFFFFFFFFDFF, $FFFFFFFFFFFFFBFF, $FFFFFFFFFFFFF7FF,
  317.     $FFFFFFFFFFFFEFFF, $FFFFFFFFFFFFDFFF, $FFFFFFFFFFFFBFFF, $FFFFFFFFFFFF7FFF,
  318.     $FFFFFFFFFFFEFFFF, $FFFFFFFFFFFDFFFF, $FFFFFFFFFFFBFFFF, $FFFFFFFFFFF7FFFF,
  319.     $FFFFFFFFFFEFFFFF, $FFFFFFFFFFDFFFFF, $FFFFFFFFFFBFFFFF, $FFFFFFFFFF7FFFFF,
  320.     $FFFFFFFFFEFFFFFF, $FFFFFFFFFDFFFFFF, $FFFFFFFFFBFFFFFF, $FFFFFFFFF7FFFFFF,
  321.     $FFFFFFFFEFFFFFFF, $FFFFFFFFDFFFFFFF, $FFFFFFFFBFFFFFFF, $FFFFFFFF7FFFFFFF,
  322.     $FFFFFFFEFFFFFFFF, $FFFFFFFDFFFFFFFF, $FFFFFFFBFFFFFFFF, $FFFFFFF7FFFFFFFF,
  323.     $FFFFFFEFFFFFFFFF, $FFFFFFDFFFFFFFFF, $FFFFFFBFFFFFFFFF, $FFFFFF7FFFFFFFFF,
  324.     $FFFFFEFFFFFFFFFF, $FFFFFDFFFFFFFFFF, $FFFFFBFFFFFFFFFF, $FFFFF7FFFFFFFFFF,
  325.     $FFFFEFFFFFFFFFFF, $FFFFDFFFFFFFFFFF, $FFFFBFFFFFFFFFFF, $FFFF7FFFFFFFFFFF,
  326.     $FFFEFFFFFFFFFFFF, $FFFDFFFFFFFFFFFF, $FFFBFFFFFFFFFFFF, $FFF7FFFFFFFFFFFF,
  327.     $FFEFFFFFFFFFFFFF, $FFDFFFFFFFFFFFFF, $FFBFFFFFFFFFFFFF, $FF7FFFFFFFFFFFFF,
  328.     $FEFFFFFFFFFFFFFF, $FDFFFFFFFFFFFFFF, $FBFFFFFFFFFFFFFF, $F7FFFFFFFFFFFFFF,
  329.     $EFFFFFFFFFFFFFFF, $DFFFFFFFFFFFFFFF, $BFFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF);
  330.  
  331. implementation
  332.  
  333. resourcestring
  334.   LngEBitStringInvalidCharacter = 'The bitstring "%s" contains a invalid ' +
  335.     'character. Unexpected character "%s" at position "%d".';
  336.   LngEBitStringTooLong = 'The bitstring "%s" is too long. Expected: %d byte.';
  337.  
  338. function GetByteBitArray(AByte: Byte): TByteBitArray;
  339. var
  340.   i: T8BitPos;
  341. begin
  342.   for i := Low(T8BitPos) to High(T8BitPos) do
  343.   begin
  344.     // result[i] := GetByteBit(AByte, i);
  345.     result[i] := AByte and SingleBitArray[i] = SingleBitArray[i];
  346.   end;
  347. end;
  348.  
  349. function GetNibbleBitArray(ANibble: Nibble): THexNibbleBitArray;
  350. var
  351.   i: T4BitPos;
  352. begin
  353.   for i := Low(T4BitPos) to High(T4BitPos) do
  354.   begin
  355.     // result[i] := GetNibbleBit(ANibble, i);
  356.     result[i] := ANibble and SingleBitArray[i] = SingleBitArray[i];
  357.   end;
  358. end;
  359.  
  360. function BuildByte(AUpperNibble, ALowerNibble: THexNibble): Byte;
  361. begin
  362.   // result := $10 * AUpperNibble + ALowerNibble;
  363.   result := (AUpperNibble shl 4) + ALowerNibble;
  364. end;
  365.  
  366. function BuildByte(ABitArray: TByteBitArray): Byte;
  367. var
  368.   i: T8BitPos;
  369. begin
  370.   result := 0;
  371.   for i := Low(T8BitPos) to High(T8BitPos) do
  372.   begin
  373.     // SetByteBit(result, i, ABitArray[i]);
  374.  
  375.     if not ABitArray[i] then
  376.       result := result and SingleBitArrayDynamicInversed[i]
  377.     else
  378.       result := result or SingleBitArray[i];
  379.   end;
  380. end;
  381.  
  382. function BuildByte(ABits: TByteBitString): Byte;
  383. begin
  384.   result := BuildByte(ByteBitArrayFromBitString(ABits));
  385. end;
  386.  
  387. function BuildByte(ABit1, ABit2, ABit3, ABit4, ABit5, ABit6, ABit7,
  388.   ABit8: TBit): Byte; overload;
  389. var
  390.   ba: TByteBitArray;
  391. begin
  392.   ba[0] := ABit1;
  393.   ba[1] := ABit2;
  394.   ba[2] := ABit3;
  395.   ba[3] := ABit4;
  396.   ba[4] := ABit5;
  397.   ba[5] := ABit6;
  398.   ba[6] := ABit7;
  399.   ba[7] := ABit8;
  400.   result := BuildByte(ba);
  401. end;
  402.  
  403. function ByteBitArrayFromBitString(const ABits: TByteBitString): TByteBitArray;
  404. var
  405.   i: integer;
  406. begin
  407.   if Length(ABits) <> 8 then
  408.   begin
  409.     raise EBitStringTooLong.CreateFmt(LngEBitStringTooLong, [ABits, 8]);
  410.     exit;
  411.   end;
  412.  
  413.   for i := 1 to Length(ABits) do
  414.   begin
  415.     case ABits[i] of
  416.       '0': result[i-1] := false;
  417.       '1': result[i-1] := true;
  418.     else
  419.       raise EBitStringInvalidCharacter.CreateFmt(LngEBitStringInvalidCharacter,
  420.         [ABits, ABits[i], i]);
  421.     end;
  422.   end;
  423. end;
  424.  
  425. function NibbleBitArrayFromBitString(const ABits: THexNibbleBitString):
  426.   THexNibbleBitArray;
  427. var
  428.   i: integer;
  429. begin
  430.   if Length(ABits) <> 4 then
  431.   begin
  432.     raise EBitStringTooLong.CreateFmt(LngEBitStringTooLong, [ABits, 4]);
  433.     exit;
  434.   end;
  435.  
  436.   for i := 1 to Length(ABits) do
  437.   begin
  438.     case ABits[i] of
  439.       '0': result[i-1] := false;
  440.       '1': result[i-1] := true;
  441.     else
  442.       raise EBitStringInvalidCharacter.CreateFmt(LngEBitStringInvalidCharacter,
  443.         [ABits, ABits[i], i]);
  444.     end;
  445.   end;
  446. end;
  447.  
  448. function BuildNibble(ABit1, ABit2, ABit3, ABit4: TBit): Nibble;
  449. var
  450.   ba: THexNibbleBitArray;
  451. begin
  452.   ba[0] := ABit1;
  453.   ba[1] := ABit2;
  454.   ba[2] := ABit3;
  455.   ba[3] := ABit4;
  456.   result := BuildNibble(ba);
  457. end;
  458.  
  459. function BuildNibble(ABitArray: THexNibbleBitArray): Nibble;
  460. var
  461.   i: T4BitPos;
  462. begin
  463.   result := 0;
  464.   for i := Low(T4BitPos) to High(T4BitPos) do
  465.   begin
  466.     // SetNibbleBit(result, i, ABitArray[i]);
  467.  
  468.     if not ABitArray[i] then
  469.       result := result and SingleBitArrayDynamicInversed[i]
  470.     else
  471.       result := result or SingleBitArray[i];
  472.   end;
  473. end;
  474.  
  475. function BuildNibble(ABits: THexNibbleBitString): Nibble;
  476. begin
  477.   result := BuildNibble(NibbleBitArrayFromBitString(ABits));
  478. end;
  479.  
  480. function GetLowerNibble(AByte: Byte): THexNibble;
  481. begin
  482.   result := AByte and AllSetBitsNibble[0];
  483. end;
  484.  
  485. function SetLowerNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
  486. begin
  487.   // result := BuildByte(GetUpperNibble(AByte), ANewNibble);
  488.   // result := $10 * (AByte and AllSetBitsNibble[1] shr 4) + ANewNibble;
  489.   // result := (AByte and AllSetBitsNibble[1] shr 4) shl 4 + ANewNibble;
  490.  
  491.   // Optimized: "shr 4 shl 4" removed
  492.   result := (AByte and AllSetBitsNibble[1]) + ANewNibble;
  493. end;
  494.  
  495. function GetUpperNibble(AByte: Byte): THexNibble;
  496. begin
  497.   result := AByte and AllSetBitsNibble[1] shr 4;
  498. end;
  499.  
  500. function SetUpperNibble(AByte: Byte; ANewNibble: THexNibble): Byte;
  501. begin
  502.   // result := BuildByte(ANewNibble, GetLowerNibble(AByte));
  503.   // result := ($10 * ANewNibble) + (AByte and AllSetBitsNibble[0]);
  504.   result := (ANewNibble shl 4) + (AByte and AllSetBitsNibble[0]);
  505. end;
  506.  
  507. function GetByteBit(AByte: Byte; ABitPos: T8BitPos): TBit;
  508. begin
  509.   // result := AByte and SingleBitArray[ABitPos] shr ABitPos = 1;
  510.   // result := AByte and Math.Power(2, ABitPos) shr ABitPos = 1;
  511.   // result := AByte and SingleBitArray[ABitPos] shr ABitPos = 1;
  512.   result := AByte and SingleBitArray[ABitPos] = SingleBitArray[ABitPos];
  513. end;
  514.  
  515. function SetByteBit(AByte: Byte; ABitPos: T8BitPos; ANewBit: TBit): Byte;
  516. begin
  517.   if not ANewBit then
  518.   begin
  519.     // Set a bit to 0.
  520.     // Example: abcdefgh AND 11111011 = abcde0gh
  521.  
  522.     // result := AByte and (AllSetBitsBytes[0] - SingleBitArray[ABitPos]);
  523.     // result := AByte and (AllSetBitsBytes[0] - Math.Power(2, ABitPos));
  524.     result := AByte and SingleBitArrayDynamicInversed[ABitPos]
  525.   end
  526.   else
  527.   begin
  528.     // Set a bit to 1.
  529.     // Example: abcdefgh OR 00000100 = abcde1gh
  530.  
  531.     // result := AByte or Math.Power(2, ABitPos);
  532.     result := AByte or SingleBitArray[ABitPos];
  533.   end;
  534. end;
  535.  
  536. function GetAnsiCharBit(AChar: AnsiChar; ABitPos: T8BitPos): TBit;
  537. begin
  538.   result := GetByteBit(Ord(AChar), ABitPos);
  539. end;
  540.  
  541. function SetAnsiCharBit(AChar: AnsiChar; ABitPos: T8BitPos; ANewBit: TBit): Byte;
  542. begin
  543.   result := SetByteBit(Ord(AChar), ABitPos, ANewBit);
  544. end;
  545.  
  546. function GetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos): TBit;
  547. begin
  548.   result := GetByteBit(ANibble, ABitPos);
  549. end;
  550.  
  551. function SetNibbleBit(ANibble: Nibble; ABitPos: T4BitPos;
  552.   ANewBit: TBit): Nibble;
  553. begin
  554.   result := SetByteBit(ANibble, ABitPos, ANewBit);
  555. end;
  556.  
  557. function ByteBitArrayShr(ABitArray: TByteBitArray;
  558.   AVal: Longword): TByteBitArray;
  559. var
  560.   b: Byte;
  561. begin
  562.   b := BuildByte(ABitArray);
  563.   result := GetByteBitArray(b shr AVal);
  564. end;
  565.  
  566. function ByteBitArrayShl(ABitArray: TByteBitArray;
  567.   AVal: Longword): TByteBitArray;
  568. var
  569.   b: Byte;
  570. begin
  571.   b := BuildByte(ABitArray);
  572.   result := GetByteBitArray(b shl AVal);
  573. end;
  574.  
  575. function ByteBitArrayAnd(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
  576. var
  577.   b, b2: Byte;
  578. begin
  579.   b  := BuildByte(ABitArray);
  580.   b2 := BuildByte(ABitArray2);
  581.   result := GetByteBitArray(b and b2);
  582. end;
  583.  
  584. function ByteBitArrayOr(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
  585. var
  586.   b, b2: Byte;
  587. begin
  588.   b  := BuildByte(ABitArray);
  589.   b2 := BuildByte(ABitArray2);
  590.   result := GetByteBitArray(b or b2);
  591. end;
  592.  
  593. function ByteBitArrayXor(ABitArray, ABitArray2: TByteBitArray): TByteBitArray;
  594. var
  595.   b, b2: Byte;
  596. begin
  597.   b  := BuildByte(ABitArray);
  598.   b2 := BuildByte(ABitArray2);
  599.   result := GetByteBitArray(b xor b2);
  600. end;
  601.  
  602. function ByteBitArrayNot(ABitArray: TByteBitArray): TByteBitArray;
  603. var
  604.   b: Byte;
  605. begin
  606.   b := BuildByte(ABitArray);
  607.   result := GetByteBitArray(not b);
  608. end;
  609.  
  610. function NibbleBitArrayShr(ABitArray: THexNibbleBitArray; AVal: Longword):
  611.   THexNibbleBitArray;
  612. var
  613.   b: Nibble;
  614. begin
  615.   b := BuildNibble(ABitArray);
  616.   result := GetNibbleBitArray(b shr AVal);
  617. end;
  618.  
  619. function NibbleBitArrayShl(ABitArray: THexNibbleBitArray; AVal: Longword):
  620.   THexNibbleBitArray;
  621. var
  622.   b: Nibble;
  623. begin
  624.   b := BuildNibble(ABitArray);
  625.   result := GetNibbleBitArray(b shl AVal);
  626. end;
  627.  
  628. function NibbleBitArrayAnd(ABitArray, ABitArray2: THexNibbleBitArray):
  629.   THexNibbleBitArray;
  630. var
  631.   b, b2: Nibble;
  632. begin
  633.   b  := BuildNibble(ABitArray);
  634.   b2 := BuildNibble(ABitArray2);
  635.   result := GetNibbleBitArray(b and b2);
  636. end;
  637.  
  638. function NibbleBitArrayOr(ABitArray, ABitArray2: THexNibbleBitArray):
  639.   THexNibbleBitArray;
  640. var
  641.   b, b2: Nibble;
  642. begin
  643.   b  := BuildNibble(ABitArray);
  644.   b2 := BuildNibble(ABitArray2);
  645.   result := GetNibbleBitArray(b or b2);
  646. end;
  647.  
  648. function NibbleBitArrayXor(ABitArray, ABitArray2: THexNibbleBitArray):
  649.   THexNibbleBitArray;
  650. var
  651.   b, b2: Nibble;
  652. begin
  653.   b  := BuildNibble(ABitArray);
  654.   b2 := BuildNibble(ABitArray2);
  655.   result := GetNibbleBitArray(b xor b2);
  656. end;
  657.  
  658. function NibbleBitArrayNot(ABitArray: THexNibbleBitArray): THexNibbleBitArray;
  659. var
  660.   b: Nibble;
  661. begin
  662.   b := BuildNibble(ABitArray);
  663.   result := GetNibbleBitArray(not b);
  664. end;
  665.  
  666. function InverseByteBits(x: Byte): Byte;
  667. begin
  668.   //     10110001
  669.   // xor 11111111
  670.   //   = 01001110
  671.   result := x xor AllSetBitsBytes[0];
  672. end;
  673.  
  674. function InverseNibbleBits(x: Nibble): Nibble;
  675. begin
  676.   //         0001
  677.   // xor     1111
  678.   //   =     1110
  679.   result := x xor AllSetBitsNibbles[0];
  680. end;
  681.  
  682. function InterchangeNibbles(AByte: Byte): Byte;
  683. begin
  684.   // result := BuildByte(GetLowerNibble(AByte), GetUpperNibble(AByte));
  685.   result := (AByte and AllSetBitsNibble[0] shl 4) +
  686.             (AByte and AllSetBitsNibble[1] shr 4)
  687. end;
  688.  
  689. function ReverseByteBitSequence(AByte: Byte): Byte;
  690. var
  691.   ba: TByteBitArray;
  692. begin
  693.   ba := GetByteBitArray(AByte);
  694.   result := BuildByte(ba[7], ba[6], ba[5], ba[4], ba[3], ba[2], ba[1], ba[0]);
  695. end;
  696.  
  697. function ReverseNibbleBitSequence(ANibble: Nibble): Nibble;
  698. var
  699.   ba: THexNibbleBitArray;
  700. begin
  701.   ba := GetNibbleBitArray(ANibble);
  702.   result := BuildNibble(ba[3], ba[2], ba[1], ba[0]);
  703. end;
  704.  
  705. end.
  706.