对一个CNPack编码单元的改进.速度提升了十几倍.也就是1000%
CNBase64.pas
编码单元.
改进解码也是查表.速度会提高.
另外原来的单元编码解码过滤都是用字符串相加的方式,会导致一次次内存的销毁和创建.改成了进算长度一次性分配的方式.
经过测试:旧的编码要1110毫秒的数据改进后只要125毫秒.
旧的解码要6455毫秒的数据改进后只要210毫秒
改进后的单元如下:
unit CnBase64;
interface
uses
SysUtils;
function Base64Encode(InputData:string;var OutputData:string):Byte;
function Base64Decode(InputData:string;var OutputData:string):Byte;
const
BASE64_OK = 0; // 转换成功
BASE64_ERROR = 1; // 转换错误(未知错误) (e.g. can't encode octet in input stream) -> error in implementation
BASE64_INVALID = 2; // 输入的字符串中有非法字符 (在 FilterDecodeInput=False 时可能出现)
BASE64_LENGTH = 3; // 数据长度非法
BASE64_DATALEFT = 4; // too much input data left (receveived 'end of encoded data' but not end of input string)
BASE64_PADDING = 5; // 输入的数据未能以正确的填充字符结束
implementation
const
//------------------------------------------------------------------------------
// 编码的参考表
//------------------------------------------------------------------------------
EnCodeTab: array[0..64] of Char =
(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
'=');
//------------------------------------------------------------------------------
//解码的参考表
//------------------------------------------------------------------------------
{不包含在Base64里面的字符直接给零,反正也取不到}
DecodeTable: array[#0..#127] of Byte =
(
Byte('='), 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 62, 00, 00, 00, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 00, 00, 00, 00, 00, 00,
00, 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, 00, 00, 00, 00, 00,
00, 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, 00, 00, 00, 00, 00
);
var
FilterDecodeInput:Boolean=True;
function Base64Encode(InputData:string;var OutputData:string):Byte;
var
Times, SrcLen, i: integer;
x1, x2, x3, x4: char;
xt: byte;
begin
SrcLen := length(InputData);
if SrcLen mod 3 = 0 then
Times := SrcLen div 3
else
Times := SrcLen div 3 + 1;
SetLength(OutputData, Times * 4); //一次分配整块内存,避免一次次字符串相加,一次次释放分配内存
for i := 0 to times - 1 do
begin
if SrcLen >= (3 + i * 3) then
begin
x1 := EnCodeTab[(ord(InputData[1 + i * 3]) shr 2)];
xt := (ord(InputData[1 + i * 3]) shl 4) and 48;
xt := xt or (ord(InputData[2 + i * 3]) shr 4);
x2 := EnCodeTab[xt];
xt := (Ord(InputData[2 + i * 3]) shl 2) and 60;
xt := xt or (ord(InputData[3 + i * 3]) shr 6);
x3 := EnCodeTab[xt];
xt := (ord(InputData[3 + i * 3]) and 63);
x4 := EnCodeTab[xt];
end
else if SrcLen >= (2 + i * 3) then
begin
x1 := EnCodeTab[(ord(InputData[1 + i * 3]) shr 2) ];
xt := (ord(InputData[1 + i * 3]) shl 4) and 48;
xt := xt or (ord(InputData[2 + i * 3]) shr 4);
x2 := EnCodeTab[xt];
xt := (ord(InputData[2 + i * 3]) shl 2) and 60;
x3 := EnCodeTab[xt ];
x4 := '=';
end
else
begin
x1 := EnCodeTab[(ord(InputData[1 + i * 3]) shr 2)];
xt := (ord(InputData[1 + i * 3]) shl 4) and 48;
x2 := EnCodeTab[xt];
x3 := '=';
x4 := '=';
end;
OutputData[I shl 2 + 1] := X1;
OutputData[I shl 2 + 2] := X2;
OutputData[I shl 2 + 3] := X3;
OutputData[I shl 2 + 4] := X4;
end;
result:=BASE64_OK;
end;
function Base64Decode(InputData:string;var OutputData:string):Byte;
var
SrcLen, Times, i: integer;
x1, x2, x3, x4, xt: byte;
C: Integer;
function FilterLine(Source:String): string;
var
P, PP: PChar;
I: Integer;
begin
SrcLen := Length(Source);
GetMem(P, Srclen); //一次分配整块内存,避免一次次字符串相加,一次次释放分配内存
PP := P;
FillChar(P^, Srclen, 0);
for I := 1 to SrcLen do
begin
if Source[I] in ['0'..'9', 'A'..'Z', 'a'..'z', '+', '/', '='] then
begin
PP^ := Source[I];
Inc(PP);
end;
end;
SetString(Result, P, PP - P); //截取有效部分
FreeMem(P, SrcLen);
end;
begin
if (InputData='') then
begin
result:=BASE64_OK;
exit;
end;
OutPutData:='';
if FilterDecodeInput then
InputData:=FilterLine(InputData);
SrcLen := Length(InputData);
SetLength(OutputData, (SrcLen * 3 div 4)); //一次分配整块内存,避免一次次字符串相加,一次次释放分配内存
Times := SrcLen div 4;
C := 1;
for i := 0 to Times - 1 do
begin
x1 := DecodeTable[InputData[1 + i shl 2]];
x2 := DecodeTable[InputData[2 + i shl 2]];
x3 := DecodeTable[InputData[3 + i shl 2]];
x4 := DecodeTable[InputData[4 + i shl 2]];
x1 := x1 shl 2;
xt := x2 shr 4;
x1 := x1 or xt;
x2 := x2 shl 4;
OutputData[C] := Chr(x1);
Inc(C);
if x3 = 64 then
break;
xt := x3 shr 2;
x2 := x2 or xt;
x3 := x3 shl 6;
OutputData[C] := Chr(x2);
Inc(C);
if x4 = 64 then
break;
x3 := x3 or x4;
OutputData[C] := Chr(x3);
Inc(C);
end;
result:=BASE64_OK;
end;
end.
|