lazarus-ccr/wst/trunk/basex_encode.pas
inoussa 6a2cfcfb33 AnsiChar and WideChar implementation
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1853 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2011-08-29 02:44:55 +00:00

654 lines
22 KiB
ObjectPascal

{ This file is part of the Web Service Toolkit
Copyright (c) 2006, 2007 by Inoussa OUEDRAOGO
This file is provide under modified LGPL licence
( the files COPYING.modifiedLGPL and COPYING.LGPL).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
}
{$INCLUDE wst_global.inc}
{$RANGECHECKS OFF}
unit basex_encode;
interface
uses
SysUtils, wst_types;
type
EBaseXException = class(Exception);
EBase16Exception = class(EBaseXException);
EBase32Exception = class(EBaseXException);
EBase64Exception = class(EBaseXException);
TBaseXOption = ( xoDecodeIgnoreIllegalChar );
TBaseXOptions = set of TBaseXOption;
function Base64Encode(const ALength : PtrInt; const AInBuffer) : string;overload;
function Base64Encode(const AInBuffer : TBinaryString) : string;overload;
function Base64Decode(const AInBuffer : string; const AOptions : TBaseXOptions) : TByteDynArray;overload;
function Base32Encode(const ALength : PtrInt; const AInBuffer) : string; overload;
function Base32Encode(const AInBuffer : TBinaryString) : string; overload;
function Base32Decode(const AInBuffer : string; const AOptions : TBaseXOptions) : TByteDynArray;
procedure Base16Encode(const ABin; const ALen : Integer; AOutBuffer : PAnsiChar); overload;
procedure Base16Encode(const ABin; const ALen : Integer; AOutBuffer : PWideChar); overload;
function Base16Encode(const ABin; const ALen : Integer) : string; overload;
function Base16Encode(const AInBuffer : TBinaryString) : string;overload;
function Base16Decode(
const AHex : PAnsiChar;
var ABin;
const ABinLen : Integer;
const AOptions : TBaseXOptions = [xoDecodeIgnoreIllegalChar]
) : Integer;overload;
function Base16Decode(
const AHex : PWideChar;
var ABin;
const ABinLen : Integer;
const AOptions : TBaseXOptions = [xoDecodeIgnoreIllegalChar]
) : Integer;overload;
function Base16Decode(const AInBuffer : ansistring; const AOptions : TBaseXOptions) : TByteDynArray;overload;
implementation
uses
wst_consts;
const
Base64_CHAR_TABLE : array[0..63] of char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
IM = 255; INVALID_MARKER = IM;
Base64_CHAR_INDEX_TABLE : array[Byte] of Byte = (
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,62,IM,IM,IM,63,
52,53,54,55,56,57,58,59,60,61,IM,IM,IM,00,IM,IM,
IM,00,01,02,03,04,05,06,07,08,09,10,11,12,13,14,
15,16,17,18,19,20,21,22,23,24,25,IM,IM,IM,IM,IM,
IM,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,
IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM,IM
);
//Base64_CHAR_SET = ['A'..'Z','a'..'z','0'..'9','+','/'];
function Base64Encode(const ALength : PtrInt; const AInBuffer) : string;
var
locBuffer : PByte;
locCopied, locBlockCount, i, locAtualLen : PtrInt;
locInQuantom : array[0..2] of Byte;
locOutQuantom : array[0..3] of Char;
begin
Result := '';
if ( ALength > 0 ) then begin
locBuffer := @AInBuffer;
locBlockCount := ALength div 3;
SetLength(Result,(locBlockCount + 1 ) * 4);
locAtualLen := 0;
for i := 1 to locBlockCount do begin
Move(locBuffer^,locInQuantom[0],3);
Inc(locBuffer,3);
locOutQuantom[0] := Base64_CHAR_TABLE[( locInQuantom[0] shr 2 )];
locOutQuantom[1] := Base64_CHAR_TABLE[( ( locInQuantom[0] and 3 ) shl 4 ) or ( locInQuantom[1] shr 4 )];
locOutQuantom[2] := Base64_CHAR_TABLE[( ( locInQuantom[1] and 15 ) shl 2 ) or ( locInQuantom[2] shr 6 )];
locOutQuantom[3] := Base64_CHAR_TABLE[( locInQuantom[2] and 63 )];
Move(locOutQuantom[0],Result[locAtualLen + 1],( 4 * SizeOf(Char) ));
Inc(locAtualLen,4);
end;
locCopied := ALength mod 3;
if ( locCopied > 0 ) then begin
case locCopied of
1 :
begin
Move(locBuffer^,locInQuantom[0],1);
locInQuantom[1] := 0;
locOutQuantom[0] := Base64_CHAR_TABLE[( locInQuantom[0] shr 2 )];
locOutQuantom[1] := Base64_CHAR_TABLE[( ( locInQuantom[0] and 3 ) shl 4 ) or ( locInQuantom[1] shr 4 )];
locOutQuantom[2] := '=';
locOutQuantom[3] := '=';
end;
2 :
begin
Move(locBuffer^,locInQuantom[0],2);
locInQuantom[2] := 0;
locOutQuantom[0] := Base64_CHAR_TABLE[( locInQuantom[0] shr 2 )];
locOutQuantom[1] := Base64_CHAR_TABLE[( ( locInQuantom[0] and 3 ) shl 4 ) or ( locInQuantom[1] shr 4 )];
locOutQuantom[2] := Base64_CHAR_TABLE[( ( locInQuantom[1] and 15 ) shl 2 ) or ( locInQuantom[2] shr 6 )];
locOutQuantom[3] := '=';
end;
end;
Move(locOutQuantom[0],Result[locAtualLen + 1],( 4 * SizeOf(Char) ));
Inc(locAtualLen,4);
end;
SetLength(Result,locAtualLen);
end;
end;
function Base64Encode(const AInBuffer : TBinaryString) : string;
begin
if ( Length(AInBuffer) = 0 ) then
Result := ''
else
Result := Base64Encode(Length(AInBuffer),AInBuffer[1]);
end;
function Base64Decode(const AInBuffer : string; const AOptions : TBaseXOptions) : TByteDynArray;
var
locBuffer : PChar;
locInLen, locInIndex, i, locPadded : PtrInt;
locOutQuantom : array[0..2] of Byte;
locInQuantom : array[0..3] of Byte;
ok : Boolean;
locAtualLen : PtrInt;
locInValue, locReadedValidChars : Byte;
locFailOnIllegalChar : Boolean;
begin
if ( AInBuffer = '' ) then begin
Result := nil;
end else begin
locInIndex := 0;
locAtualLen := 0;
locPadded := 0;
locInLen := Length(AInBuffer);
SetLength(Result,locInLen);
locBuffer := @(AInBuffer[1]);
locFailOnIllegalChar := not ( xoDecodeIgnoreIllegalChar in AOptions );
while ( locInIndex < locInLen ) do begin
locReadedValidChars := 0;
for i := 0 to 3 do begin
ok := False;
while ( locInIndex <= locInLen ) do begin
{$IF SizeOf(Char) > SizeOf(Byte) }
if ( Ord(locBuffer^) > High(Byte) ) then
locInValue := INVALID_MARKER
else
locInValue := Base64_CHAR_INDEX_TABLE[Ord(locBuffer^)];
{$ELSE}
locInValue := Base64_CHAR_INDEX_TABLE[Ord(locBuffer^)];
{$IFEND}
Inc(locBuffer);
Inc(locInIndex);
if ( locInValue <> INVALID_MARKER ) then begin
locInQuantom[i] := locInValue;
if ( locBuffer^ = '=' ) then begin
Inc(locPadded);
end;
ok := True;
Inc(locReadedValidChars);
Break;
end else begin
if locFailOnIllegalChar then
raise EBase64Exception.Create(SERR_InvalidEncodedData);
end;
end;
if ( not ok ) and locFailOnIllegalChar then
raise EBase64Exception.CreateFmt(SERR_IllegalChar,[Char(locBuffer^)]);
end;
if ( locReadedValidChars > 0 ) then begin
locOutQuantom[0] := ( locInQuantom[0] shl 2 ) or ( locInQuantom[1] shr 4 );
locOutQuantom[1] := ( locInQuantom[1] shl 4 ) or ( locInQuantom[2] shr 2 );
locOutQuantom[2] := ( locInQuantom[2] shl 6 ) or ( locInQuantom[3] );
Move(locOutQuantom[0],Result[locAtualLen],3 - locPadded);
Inc(locAtualLen,3 - locPadded);
end;
end;
SetLength(Result,locAtualLen);
end;
end;
function Base64DecodeStr(const AInBuffer : string; const AOptions : TBaseXOptions) : TBinaryString;
var
locRes : TByteDynArray;
begin
locRes := Base64Decode(AInBuffer,AOptions);
SetLength(Result,Length(locRes));
if ( Length(Result) > 0 ) then
Move(locRes[0],Result[1],Length(Result));
end;
const
Base32_CHAR_TABLE : array[0..31] of char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
function Base32Encode(const ALength : PtrInt; const AInBuffer) : string;
var
locBuffer : PByte;
locCopied, locBlockCount, i, locAtualLen : PtrInt;
locInQuantom : array[0..4] of Byte;
locOutQuantom : array[0..7] of Char;
begin
Result := '';
if ( ALength > 0 ) then begin
locBuffer := @AInBuffer;
locBlockCount := ALength div 5;
SetLength(Result,(locBlockCount + 1 ) * 8);
locAtualLen := 0;
for i := 1 to locBlockCount do begin
Move(locBuffer^,locInQuantom[0],5);
Inc(locBuffer,5);
locOutQuantom[0] := Base32_CHAR_TABLE[(locInQuantom[0] shr 3)];
locOutQuantom[1] := Base32_CHAR_TABLE[( (locInQuantom[0] and 7) shl 2 ) or ( locInQuantom[1] shr 6 )];
locOutQuantom[2] := Base32_CHAR_TABLE[( (locInQuantom[1] and 62) shr 1 )];
locOutQuantom[3] := Base32_CHAR_TABLE[( (locInQuantom[1] and 1) shl 4 ) or ( locInQuantom[2] shr 4 )];
locOutQuantom[4] := Base32_CHAR_TABLE[( (locInQuantom[2] and 15) shl 1 ) or ( locInQuantom[3] shr 7 )];
locOutQuantom[5] := Base32_CHAR_TABLE[( (locInQuantom[3] and 124) shr 2 )];
locOutQuantom[6] := Base32_CHAR_TABLE[( (locInQuantom[3] and 3) shl 3 ) or ( locInQuantom[4] shr 5 )];
locOutQuantom[7] := Base32_CHAR_TABLE[(locInQuantom[4] and 31)];
Move(locOutQuantom[0],Result[locAtualLen + 1],( 8 * SizeOf(Char) ));
Inc(locAtualLen,8);
end;
locCopied := ALength mod 5;
if ( locCopied > 0 ) then begin
case locCopied of
1 :
begin
Move(locBuffer^,locInQuantom[0],1);
locInQuantom[1] := 0;
locOutQuantom[0] := Base32_CHAR_TABLE[(locInQuantom[0] shr 3)];
locOutQuantom[1] := Base32_CHAR_TABLE[( (locInQuantom[0] and 7) shl 2 ) or ( locInQuantom[1] shr 6 )];
locOutQuantom[2] := '=';
locOutQuantom[3] := '=';
locOutQuantom[4] := '=';
locOutQuantom[5] := '=';
locOutQuantom[6] := '=';
locOutQuantom[7] := '=';
end;
2 :
begin
Move(locBuffer^,locInQuantom[0],2);
locInQuantom[2] := 0;
locOutQuantom[0] := Base32_CHAR_TABLE[(locInQuantom[0] shr 3)];
locOutQuantom[1] := Base32_CHAR_TABLE[( (locInQuantom[0] and 7) shl 2 ) or ( locInQuantom[1] shr 6 )];
locOutQuantom[2] := Base32_CHAR_TABLE[( (locInQuantom[1] and 62) shr 1 )];
locOutQuantom[3] := Base32_CHAR_TABLE[( (locInQuantom[1] and 1) shl 4 ) or ( locInQuantom[2] shr 4 )];
locOutQuantom[4] := '=';
locOutQuantom[5] := '=';
locOutQuantom[6] := '=';
locOutQuantom[7] := '=';
end;
3 :
begin
Move(locBuffer^,locInQuantom[0],3);
locInQuantom[3] := 0;
locOutQuantom[0] := Base32_CHAR_TABLE[(locInQuantom[0] shr 3)];
locOutQuantom[1] := Base32_CHAR_TABLE[( (locInQuantom[0] and 7) shl 2 ) or ( locInQuantom[1] shr 6 )];
locOutQuantom[2] := Base32_CHAR_TABLE[( (locInQuantom[1] and 62) shr 1 )];
locOutQuantom[3] := Base32_CHAR_TABLE[( (locInQuantom[1] and 1) shl 4 ) or ( locInQuantom[2] shr 4 )];
locOutQuantom[4] := Base32_CHAR_TABLE[( (locInQuantom[2] and 15) shl 1 ) or ( locInQuantom[3] shr 7 )];
locOutQuantom[5] := '=';
locOutQuantom[6] := '=';
locOutQuantom[7] := '=';
end;
4 :
begin
Move(locBuffer^,locInQuantom[0],4);
locInQuantom[4] := 0;
locOutQuantom[0] := Base32_CHAR_TABLE[(locInQuantom[0] shr 3)];
locOutQuantom[1] := Base32_CHAR_TABLE[( (locInQuantom[0] and 7) shl 2 ) or ( locInQuantom[1] shr 6 )];
locOutQuantom[2] := Base32_CHAR_TABLE[( (locInQuantom[1] and 62) shr 1 )];
locOutQuantom[3] := Base32_CHAR_TABLE[( (locInQuantom[1] and 1) shl 4 ) or ( locInQuantom[2] shr 4 )];
locOutQuantom[4] := Base32_CHAR_TABLE[( (locInQuantom[2] and 15) shl 1 ) or ( locInQuantom[3] shr 7 )];
locOutQuantom[5] := Base32_CHAR_TABLE[( (locInQuantom[3] and 124) shr 2 )];
locOutQuantom[6] := Base32_CHAR_TABLE[( (locInQuantom[3] and 3) shl 3 ) or ( locInQuantom[4] shr 5 )];
locOutQuantom[7] := '=';
end;
end;
Move(locOutQuantom[0],Result[locAtualLen + 1],(8 * SizeOf(Char)));
Inc(locAtualLen,8);
end;
SetLength(Result,locAtualLen);
end;
end;
function Base32Encode(const AInBuffer : TBinaryString) : string;
begin
if ( Length(AInBuffer) = 0 ) then
Result := ''
else
Result := Base32Encode(Length(AInBuffer),AInBuffer[1]);
end;
function Base32Decode(const AInBuffer : string; const AOptions : TBaseXOptions) : TByteDynArray;
const
ALPHA_UP_MAP : array['A'..'Z'] of Byte = (
0 , 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25
);
ALPHA_LOW_MAP : array['a'..'z'] of Byte = (
0 , 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25
);
DIGIT_MAP : array['2'..'7'] of Byte = ( 26, 27, 28, 29, 30, 31);
var
locBuffer : PChar;
locInLen, locInIndex, i, locPadded : PtrInt;
locOutQuantom : array[0..4] of Byte;
locInQuantom : array[0..7] of Byte;
ok : Boolean;
locAtualLen : PtrInt;
locInValue, locReadedValidChars : Byte;
locFailOnIllegalChar : Boolean;
locTrueData : Integer;
begin
if ( AInBuffer = '' ) then begin
Result := nil;
end else begin
locInIndex := 0;
locAtualLen := 0;
locPadded := 0;
locInValue := 0;
locInLen := Length(AInBuffer);
SetLength(Result,locInLen);
locBuffer := @(AInBuffer[1]);
locFailOnIllegalChar := not ( xoDecodeIgnoreIllegalChar in AOptions );
while ( locInIndex < locInLen ) do begin
locReadedValidChars := 0;
for i := 0 to 7 do begin
ok := False;
while ( locInIndex <= locInLen ) do begin
case locBuffer^ of
'A'..'Z' : locInValue := ALPHA_UP_MAP[locBuffer^];
'a'..'z' : locInValue := ALPHA_LOW_MAP[locBuffer^];
'2'..'7' : locInValue := DIGIT_MAP[locBuffer^];
'=' : locInValue := 0;
else begin
if locFailOnIllegalChar then
raise EBase32Exception.CreateFmt(SERR_IllegalChar,[Char(locBuffer^)]);
Inc(locBuffer);
Inc(locInIndex);
Continue;
end;
end;
Inc(locBuffer);
Inc(locInIndex);
locInQuantom[i] := locInValue;
if ( locBuffer^ = '=' ) then
Inc(locPadded);
ok := True;
Inc(locReadedValidChars);
Break;
end;
if ( not ok ) and locFailOnIllegalChar then
raise EBase64Exception.CreateFmt(SERR_IllegalChar,[Char(locBuffer^)]);
end;
if ( locReadedValidChars > 0 ) then begin
locOutQuantom[0] := ( locInQuantom[0] shl 3 ) or ( locInQuantom[1] shr 2 );
locOutQuantom[1] := ( (locInQuantom[1] shl 6) and 192 ) or
( (locInQuantom[2] shl 1) and 62) or
(locInQuantom[3] shr 4);
locOutQuantom[2] := ((locInQuantom[3] shl 4) and 240) or ( locInQuantom[4] shr 1);
locOutQuantom[3] := ((locInQuantom[4] shl 7) and 128) or
((locInQuantom[5] shl 2) and 124) or
(locInQuantom[6] shr 3);
locOutQuantom[4] := ((locInQuantom[6] shl 5) and 224) or locInQuantom[7];
case locPadded of
6 : locTrueData := 1;
4 : locTrueData := 2;
3 : locTrueData := 3;
1 : locTrueData := 4;
else
locTrueData := 5;
end;
Move(locOutQuantom[0],Result[locAtualLen],locTrueData);
Inc(locAtualLen,locTrueData);
end;
end;
SetLength(Result,locAtualLen);
end;
end;
procedure Base16Encode(const ABin; const ALen : Integer; AOutBuffer : PAnsiChar);
const
HEX_MAP : array[0..15] of AnsiChar = '0123456789ABCDEF';
var
p : PByte;
pres : PAnsiChar;
i : Integer;
begin
if ( ALen > 0 ) then begin
pres := AOutBuffer;
p := PByte(@Abin);
for i := 1 to ALen do begin
pres^ := HEX_MAP[p^ shr 4];
PAnsiChar(PtrUInt(pres) + SizeOf(AnsiChar))^ := HEX_MAP[p^ and $F];
Inc(pres,2);
Inc(p);
end;
end;
end;
procedure Base16Encode(const ABin; const ALen : Integer; AOutBuffer : PWideChar);
const
HEX_MAP : array[0..15] of WideChar = ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
var
p : PByte;
pres : PWideChar;
i : Integer;
begin
if ( ALen > 0 ) then begin
pres := AOutBuffer;
p := PByte(@Abin);
for i := 1 to ALen do begin
pres^ := HEX_MAP[p^ shr 4];
PWideChar(PtrUInt(pres) + SizeOf(WideChar))^ := HEX_MAP[p^ and $F];
Inc(pres,2);
Inc(p);
end;
end;
end;
function Base16Encode(const ABin; const ALen : Integer) : string;
begin
if ( ALen > 0 ) then begin
SetLength(Result,(2 * ALen));
Base16Encode(ABin,ALen,PChar(@Result[1]));
end else begin
Result := '';
end;
end;
function Base16Encode(const AInBuffer : TBinaryString) : string;
begin
Result := Base16Encode(AInBuffer[1],Length(AInBuffer));
end;
// Returns the actual bytes count.
function Base16Decode(
const AHex : PAnsiChar;
var ABin;
const ABinLen : Integer;
const AOptions : TBaseXOptions = [xoDecodeIgnoreIllegalChar]
) : Integer;
const
DIGIT_MAP : array['0'..'9'] of Byte = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
ALPHA_UP_MAP : array['A'..'F'] of Byte = ( 10, 11, 12, 13, 14, 15 );
ALPHA_LOW_MAP : array['a'..'f'] of Byte = ( 10, 11, 12, 13, 14, 15 );
var
i : Integer;
hp : PAnsiChar;
bp : PByte;
binVal : Byte;
locFailOnIllegalChar : Boolean;
begin
Result := 0;
if ( ABinLen > 0 ) then begin
binVal := 0;
bp := PByte(@Abin);
hp := AHex;
locFailOnIllegalChar := not ( xoDecodeIgnoreIllegalChar in AOptions );
for i := 0 to Pred(ABinLen) do begin
if ( hp^ = #0 ) then
Break;
while ( hp^ <> #0 ) do begin
case hp^ of
'0'..'9' :
begin
binVal := ( DIGIT_MAP[hp^] shl 4);
Break;
end;
'A'..'Z' :
begin
binVal := ( ALPHA_UP_MAP[hp^] shl 4);
Break;
end;
'a'..'z' :
begin
binVal := ( ALPHA_LOW_MAP[hp^] shl 4);
Break;
end;
else
begin
if locFailOnIllegalChar then
raise EBase16Exception.Create(SERR_UnexpectedEndOfData);
end;
end;
Inc(hp);
end;
if ( hp^ = #0 ) then
raise EBase16Exception.Create(SERR_UnexpectedEndOfData);
Inc(hp);
while ( hp^ <> #0 ) do begin
case hp^ of
'0'..'9' :
begin
bp^ := binVal or DIGIT_MAP[hp^];
Break;
end;
'A'..'Z' :
begin
bp^ := binVal or ALPHA_UP_MAP[hp^];
Break;
end;
'a'..'z' :
begin
bp^ := binVal or ALPHA_LOW_MAP[hp^];
Break;
end;
else
begin
if locFailOnIllegalChar then
raise EBase16Exception.CreateFmt(SERR_IllegalChar,[hp^]);
end;
end;
Inc(hp);
end;
if ( hp^ = #0 ) then
raise EBase16Exception.Create(SERR_UnexpectedEndOfData);
Inc(hp);
Inc(bp);
end;
Result := PtrUInt(bp) - PtrUInt(@Abin);
end;
end;
// Returns the actual bytes count.
function Base16Decode(
const AHex : PWideChar;
var ABin;
const ABinLen : Integer;
const AOptions : TBaseXOptions = [xoDecodeIgnoreIllegalChar]
) : Integer;
const
DIGIT_MAP : array['0'..'9'] of Byte = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
ALPHA_UP_MAP : array['A'..'F'] of Byte = ( 10, 11, 12, 13, 14, 15 );
ALPHA_LOW_MAP : array['a'..'f'] of Byte = ( 10, 11, 12, 13, 14, 15 );
var
i : Integer;
hp : PWideChar;
bp : PByte;
binVal : Byte;
locFailOnIllegalChar : Boolean;
begin
Result := 0;
if ( ABinLen > 0 ) then begin
binVal := 0;
bp := PByte(@Abin);
hp := AHex;
locFailOnIllegalChar := not ( xoDecodeIgnoreIllegalChar in AOptions );
for i := 0 to Pred(ABinLen) do begin
if ( hp^ = #0 ) then
Break;
while ( hp^ <> #0 ) do begin
case hp^ of
'0'..'9' :
begin
binVal := ( DIGIT_MAP[AnsiChar(hp^)] shl 4);
Break;
end;
'A'..'Z' :
begin
binVal := ( ALPHA_UP_MAP[AnsiChar(hp^)] shl 4);
Break;
end;
'a'..'z' :
begin
binVal := ( ALPHA_LOW_MAP[AnsiChar(hp^)] shl 4);
Break;
end;
else
begin
if locFailOnIllegalChar then
raise EBase16Exception.Create(SERR_UnexpectedEndOfData);
end;
end;
Inc(hp);
end;
if ( hp^ = #0 ) then
raise EBase16Exception.Create(SERR_UnexpectedEndOfData);
Inc(hp);
while ( hp^ <> #0 ) do begin
case hp^ of
'0'..'9' :
begin
bp^ := binVal or DIGIT_MAP[AnsiChar(hp^)];
Break;
end;
'A'..'Z' :
begin
bp^ := binVal or ALPHA_UP_MAP[AnsiChar(hp^)];
Break;
end;
'a'..'z' :
begin
bp^ := binVal or ALPHA_LOW_MAP[AnsiChar(hp^)];
Break;
end;
else
begin
if locFailOnIllegalChar then
raise EBase16Exception.CreateFmt(SERR_IllegalChar,[hp^]);
end;
end;
Inc(hp);
end;
if ( hp^ = #0 ) then
raise EBase16Exception.Create(SERR_UnexpectedEndOfData);
Inc(hp);
Inc(bp);
end;
Result := PtrUInt(bp) - PtrUInt(@Abin);
end;
end;
function Base16Decode(const AInBuffer : ansistring; const AOptions : TBaseXOptions) : TByteDynArray;
var
i : Integer;
begin
if ( Length(AInBuffer) > 0 ) then begin
SetLength(Result,Length(AInBuffer) div 2);
i := Base16Decode(PAnsiChar(AInBuffer),Result[0],Length(Result),AOptions);
if ( i <> Length(Result) ) then
SetLength(Result,i);
end;
end;
end.