{$APPTYPE CONSOLE}
program _HexToBin;
function HexToBin(InHex : pchar; OutBin : pchar; InBinSize : ptrint) : boolean;
type
THEX_RANGE = '0'..'F';
const
HexValid : set of char = ['0'..'9', 'A'..'F'];
BinTable : array[THEX_RANGE] of pchar =
(
'0000', '0001', '0010', '0011', { 0..3 }
'0100', '0101', '0110', '0111', { 4..7 }
'1000', '1001', { 8..9 }
{ next 7 characters in the ASCII table are not hex digits }
#0, #0, #0, #0, #0, #0, #0,
'1010', '1011', '1100', '1101', { A..D }
'1110', '1111' { E..F }
);
LOWERCASE_CLEAR = not (ord('a') - ord('A')); { should be (not $20) }
NIBBLES_PER_BYTE = 2;
BITS_PER_NIBBLE = bitsizeof(byte) div NIBBLES_PER_BYTE;
var
HexLen : ptrint;
c : char;
Hex : pchar; { to walk the input }
Bin : pchar; { to set the output }
begin
result := FALSE;
if InBinSize <= 0 then exit; { validate output buffer size }
OutBin^ := #0; { initialize to null }
HexLen := strlen(InHex); { it better be null terminated }
if HexLen <= 0 then exit;
if (HexLen * BITS_PER_NIBBLE) >= InBinSize then exit; { insufficient }
Hex := InHex;
Bin := OutBin;
while TRUE do
begin
c := Hex^;
{ uppercase the digit if necessary }
if c in ['a'..'f'] then byte(c) := byte(c) and byte(LOWERCASE_CLEAR);
if not (c in HexValid) then break;
{ the four bytes that make up a nibble can be seen as a DWORD, move all }
{ four of them as a DWORD }
PDWORD(Bin)^ := PDWORD(BinTable[c])^;
inc(Bin, BITS_PER_NIBBLE); { or sizeof(DWORD), same thing }
inc(Hex); { point to next input hex digit }
if Hex^ = #0 then { exit(TRUE); } { everything went well }
begin
Bin^ := #0;
result := TRUE;
exit;
end;
end;
{ there must have been an invalid hex digit in the input, reset the }
{ output/result to empty }
OutBin^ := #0;
end;
const
TestData : packed array[0..30] of pchar =
(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F',
'01', '10', '9a', '9A', 'a9', 'A9', 'f0', 'F0', 'FF', 'ff', 'aa', 'AA',
'F01Abc48', { result fits exactly in the 32 bytes used as buffer }
'123ABCZ', { not a valid hex number }
'012345678' { bin doesn't fit in the buffer (size 32 + 1) }
);
var
OutBinBuffer : packed array[0..32] of char; { 33 bytes }
i : ptrint;
begin
writeln;
writeln;
for i := low(TestData) to high(TestData) do
begin
if HexToBin(TestData[i], OutBinBuffer, sizeof(OutBinBuffer)) then
begin
writeln(' hex : ', TestData[i]:8, ' bin : ', OutBinBuffer:32);
continue;
end;
writeln;
writeln(' hex ', TestData[i],
' is either not a valid hex number or' +
' the buffer is too small for its binary representation');
end;
writeln;
writeln(' press ENTER/RETURN to end this program');
readln;
end.