代码
{*******************************************************}
{ }
{ Delphi Visual Component Library }
{ }
{ Copyright(c) 1995-2010 Embarcadero Technologies, Inc. }
{ }
{*******************************************************}
unit EncdDecd;
interface
uses Classes, SysUtils;
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
function EncodeString(const Input: string): string;
function DecodeString(const Input: string): string;
function DecodeBase64(const Input: AnsiString): TBytes;
function EncodeBase64(const Input: Pointer; Size: Integer): AnsiString;
implementation
uses RTLConsts;
const
EncodeTable: array[0..63] of AnsiChar =
AnsiString('ABCDEFGHIJKLMNOPQRSTUVWXYZ') +
AnsiString('abcdefghijklmnopqrstuvwxyz') +
AnsiString('0123456789+/');
DecodeTable: array[#0..#127] of Integer = (
Byte('='), 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64);
type
PPacket = ^TPacket;
TPacket = packed record
case Integer of
0: (b0, b1, b2, b3: Byte);
1: (i: Integer);
2: (a: array[0..3] of Byte);
3: (c: array[0..3] of AnsiChar);
end;
TPointerStream = class(TCustomMemoryStream)
public
constructor Create(P: Pointer; Size: Integer);
function Write(const Buffer; Count: Longint): Longint; override;
end;
procedure EncodePacket(const Packet: TPacket; NumChars: Integer; OutBuf: PAnsiChar);
begin
OutBuf[0] := EnCodeTable[Packet.a[0] shr 2];
OutBuf[1] := EnCodeTable[((Packet.a[0] shl 4) or (Packet.a[1] shr 4)) and $0000003f];
if NumChars < 2 then
OutBuf[2] :&#61; &#39;&#61;&#39;
else OutBuf[2] :&#61; EnCodeTable[((Packet.a[1] shl 2) or (Packet.a[2] shr 6)) and $0000003f];
if NumChars < 3 then
OutBuf[3] :&#61; &#39;&#61;&#39;
else OutBuf[3] :&#61; EnCodeTable[Packet.a[2] and $0000003f];
end;
function DecodePacket(InBuf: PAnsiChar; var nChars: Integer): TPacket;
begin
Result.a[0] :&#61; (DecodeTable[InBuf[0]] shl 2) or
(DecodeTable[InBuf[1]] shr 4);
NChars :&#61; 1;
if InBuf[2] <> &#39;&#61;&#39; then
begin
Inc(NChars);
Result.a[1] :&#61; Byte((DecodeTable[InBuf[1]] shl 4) or (DecodeTable[InBuf[2]] shr 2));
end;
if InBuf[3] <> &#39;&#61;&#39; then
begin
Inc(NChars);
Result.a[2] :&#61; Byte((DecodeTable[InBuf[2]] shl 6) or DecodeTable[InBuf[3]]);
end;
end;
procedure EncodeStream(Input, Output: TStream);
type
PInteger &#61; ^Integer;
var
InBuf: array[0..509] of Byte;
OutBuf: array[0..1023] of AnsiChar;
BufPtr: PAnsiChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
begin
K :&#61; 0;
repeat
BytesRead :&#61; Input.Read(InBuf, SizeOf(InBuf));
I :&#61; 0;
BufPtr :&#61; OutBuf;
while I < BytesRead do
begin
if BytesRead - I < 3 then
J :&#61; BytesRead - I
else J :&#61; 3;
Packet.i :&#61; 0;
Packet.b0 :&#61; InBuf[I];
if J > 1 then
Packet.b1 :&#61; InBuf[I &#43; 1];
if J > 2 then
Packet.b2 :&#61; InBuf[I &#43; 2];
EncodePacket(Packet, J, BufPtr);
Inc(I, 3);
Inc(BufPtr, 4);
Inc(K, 4);
if K > 75 then
begin
BufPtr[0] :&#61; #$0D;
BufPtr[1] :&#61; #$0A;
Inc(BufPtr, 2);
K :&#61; 0;
end;
end;
Output.Write(Outbuf, BufPtr - PChar(&#64;OutBuf));
until BytesRead &#61; 0;
end;
procedure DecodeStream(Input, Output: TStream);
var
InBuf: array[0..75] of AnsiChar;
OutBuf: array[0..60] of Byte;
InBufPtr, OutBufPtr: PAnsiChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
procedure SkipWhite;
var
C: AnsiChar;
NumRead: Integer;
begin
while True do
begin
NumRead :&#61; Input.Read(C, 1);
if NumRead &#61; 1 then
begin
if C in [&#39;0&#39;..&#39;9&#39;,&#39;A&#39;..&#39;Z&#39;,&#39;a&#39;..&#39;z&#39;,&#39;&#43;&#39;,&#39;/&#39;,&#39;&#61;&#39;] then
begin
Input.Position :&#61; Input.Position - 1;
Break;
end;
end else Break;
end;
end;
function ReadInput: Integer;
var
WhiteFound, EndReached : Boolean;
CntRead, Idx, IdxEnd: Integer;
begin
IdxEnd:&#61; 0;
repeat
WhiteFound :&#61; False;
CntRead :&#61; Input.Read(InBuf[IdxEnd], (SizeOf(InBuf)-IdxEnd));
EndReached :&#61; CntRead < (SizeOf(InBuf)-IdxEnd);
Idx :&#61; IdxEnd;
IdxEnd :&#61; CntRead &#43; IdxEnd;
while (Idx < IdxEnd) do
begin
if not (InBuf[Idx] in [&#39;0&#39;..&#39;9&#39;,&#39;A&#39;..&#39;Z&#39;,&#39;a&#39;..&#39;z&#39;,&#39;&#43;&#39;,&#39;/&#39;,&#39;&#61;&#39;]) then
begin
Dec(IdxEnd);
if Idx < IdxEnd then
Move(InBuf[Idx&#43;1], InBuf[Idx], IdxEnd-Idx);
WhiteFound :&#61; True;
end
else
Inc(Idx);
end;
until (not WhiteFound) or (EndReached);
Result :&#61; IdxEnd;
end;
begin
repeat
SkipWhite;
BytesRead :&#61; ReadInput;
InBufPtr :&#61; InBuf;
OutBufPtr :&#61; &#64;OutBuf;
I :&#61; 0;
while I < BytesRead do
begin
Packet :&#61; DecodePacket(InBufPtr, J);
K :&#61; 0;
while J > 0 do
begin
OutBufPtr^ :&#61; AnsiChar(Packet.a[K]);
Inc(OutBufPtr);
Dec(J);
Inc(K);
end;
Inc(InBufPtr, 4);
Inc(I, 4);
end;
Output.Write(OutBuf, OutBufPtr - PAnsiChar(&#64;OutBuf));
until BytesRead &#61; 0;
end;
function EncodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr :&#61; TStringStream.Create(Input);
try
OutStr :&#61; TStringStream.Create(&#39;&#39;);
try
EncodeStream(InStr, OutStr);
Result :&#61; OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
function DecodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr :&#61; TStringStream.Create(Input);
try
OutStr :&#61; TStringStream.Create(&#39;&#39;);
try
DecodeStream(InStr, OutStr);
Result :&#61; OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
constructor TPointerStream.Create(P: Pointer; Size: Integer);
begin
SetPointer(P, Size);
end;
function TPointerStream.Write(const Buffer; Count: Longint): Longint;
var
Pos, EndPos, Size: Longint;
Mem: Pointer;
begin
Pos :&#61; Self.Position;
if (Pos >&#61; 0) and (Count > 0) then
begin
EndPos :&#61; Pos &#43; Count;
Size:&#61; Self.Size;
if EndPos > Size then
raise EStreamError.CreateRes(&#64;SMemoryStreamError);
Mem :&#61; Self.Memory;
System.Move(Buffer, Pointer(Longint(Mem) &#43; Pos)^, Count);
Self.Position :&#61; Pos;
Result :&#61; Count;
Exit;
end;
Result :&#61; 0;
end;
function DecodeBase64(const Input: AnsiString): TBytes;
var
InStr: TPointerStream;
OutStr: TBytesStream;
Len: Integer;
begin
InStr :&#61; TPointerStream.Create(PAnsiChar(Input), Length(Input));
try
OutStr :&#61; TBytesStream.Create;
try
DecodeStream(InStr, OutStr);
Result :&#61; OutStr.Bytes;
Len :&#61; OutStr.Size;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
SetLength(Result, Len);
end;
function EncodeBase64(const Input: Pointer; Size: Integer): AnsiString;
var
InStr: TPointerStream;
OutStr: TBytesStream;
begin
InStr :&#61; TPointerStream.Create(Input, Size);
try
OutStr :&#61; TBytesStream.Create;
try
EncodeStream(InStr, OutStr);
SetString(Result, PAnsiChar(OutStr.Memory), OutStr.Size);
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
end.
{ }
{ Delphi Visual Component Library }
{ }
{ Copyright(c) 1995-2010 Embarcadero Technologies, Inc. }
{ }
{*******************************************************}
unit EncdDecd;
interface
uses Classes, SysUtils;
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
function EncodeString(const Input: string): string;
function DecodeString(const Input: string): string;
function DecodeBase64(const Input: AnsiString): TBytes;
function EncodeBase64(const Input: Pointer; Size: Integer): AnsiString;
implementation
uses RTLConsts;
const
EncodeTable: array[0..63] of AnsiChar &#61;
AnsiString(&#39;ABCDEFGHIJKLMNOPQRSTUVWXYZ&#39;) &#43;
AnsiString(&#39;abcdefghijklmnopqrstuvwxyz&#39;) &#43;
AnsiString(&#39;0123456789&#43;/&#39;);
DecodeTable: array[#0..#127] of Integer &#61; (
Byte(&#39;&#61;&#39;), 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64);
type
PPacket &#61; ^TPacket;
TPacket &#61; packed record
case Integer of
0: (b0, b1, b2, b3: Byte);
1: (i: Integer);
2: (a: array[0..3] of Byte);
3: (c: array[0..3] of AnsiChar);
end;
TPointerStream &#61; class(TCustomMemoryStream)
public
constructor Create(P: Pointer; Size: Integer);
function Write(const Buffer; Count: Longint): Longint; override;
end;
procedure EncodePacket(const Packet: TPacket; NumChars: Integer; OutBuf: PAnsiChar);
begin
OutBuf[0] :&#61; EnCodeTable[Packet.a[0] shr 2];
OutBuf[1] :&#61; EnCodeTable[((Packet.a[0] shl 4) or (Packet.a[1] shr 4)) and $0000003f];
if NumChars < 2 then
OutBuf[2] :&#61; &#39;&#61;&#39;
else OutBuf[2] :&#61; EnCodeTable[((Packet.a[1] shl 2) or (Packet.a[2] shr 6)) and $0000003f];
if NumChars < 3 then
OutBuf[3] :&#61; &#39;&#61;&#39;
else OutBuf[3] :&#61; EnCodeTable[Packet.a[2] and $0000003f];
end;
function DecodePacket(InBuf: PAnsiChar; var nChars: Integer): TPacket;
begin
Result.a[0] :&#61; (DecodeTable[InBuf[0]] shl 2) or
(DecodeTable[InBuf[1]] shr 4);
NChars :&#61; 1;
if InBuf[2] <> &#39;&#61;&#39; then
begin
Inc(NChars);
Result.a[1] :&#61; Byte((DecodeTable[InBuf[1]] shl 4) or (DecodeTable[InBuf[2]] shr 2));
end;
if InBuf[3] <> &#39;&#61;&#39; then
begin
Inc(NChars);
Result.a[2] :&#61; Byte((DecodeTable[InBuf[2]] shl 6) or DecodeTable[InBuf[3]]);
end;
end;
procedure EncodeStream(Input, Output: TStream);
type
PInteger &#61; ^Integer;
var
InBuf: array[0..509] of Byte;
OutBuf: array[0..1023] of AnsiChar;
BufPtr: PAnsiChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
begin
K :&#61; 0;
repeat
BytesRead :&#61; Input.Read(InBuf, SizeOf(InBuf));
I :&#61; 0;
BufPtr :&#61; OutBuf;
while I < BytesRead do
begin
if BytesRead - I < 3 then
J :&#61; BytesRead - I
else J :&#61; 3;
Packet.i :&#61; 0;
Packet.b0 :&#61; InBuf[I];
if J > 1 then
Packet.b1 :&#61; InBuf[I &#43; 1];
if J > 2 then
Packet.b2 :&#61; InBuf[I &#43; 2];
EncodePacket(Packet, J, BufPtr);
Inc(I, 3);
Inc(BufPtr, 4);
Inc(K, 4);
if K > 75 then
begin
BufPtr[0] :&#61; #$0D;
BufPtr[1] :&#61; #$0A;
Inc(BufPtr, 2);
K :&#61; 0;
end;
end;
Output.Write(Outbuf, BufPtr - PChar(&#64;OutBuf));
until BytesRead &#61; 0;
end;
procedure DecodeStream(Input, Output: TStream);
var
InBuf: array[0..75] of AnsiChar;
OutBuf: array[0..60] of Byte;
InBufPtr, OutBufPtr: PAnsiChar;
I, J, K, BytesRead: Integer;
Packet: TPacket;
procedure SkipWhite;
var
C: AnsiChar;
NumRead: Integer;
begin
while True do
begin
NumRead :&#61; Input.Read(C, 1);
if NumRead &#61; 1 then
begin
if C in [&#39;0&#39;..&#39;9&#39;,&#39;A&#39;..&#39;Z&#39;,&#39;a&#39;..&#39;z&#39;,&#39;&#43;&#39;,&#39;/&#39;,&#39;&#61;&#39;] then
begin
Input.Position :&#61; Input.Position - 1;
Break;
end;
end else Break;
end;
end;
function ReadInput: Integer;
var
WhiteFound, EndReached : Boolean;
CntRead, Idx, IdxEnd: Integer;
begin
IdxEnd:&#61; 0;
repeat
WhiteFound :&#61; False;
CntRead :&#61; Input.Read(InBuf[IdxEnd], (SizeOf(InBuf)-IdxEnd));
EndReached :&#61; CntRead < (SizeOf(InBuf)-IdxEnd);
Idx :&#61; IdxEnd;
IdxEnd :&#61; CntRead &#43; IdxEnd;
while (Idx < IdxEnd) do
begin
if not (InBuf[Idx] in [&#39;0&#39;..&#39;9&#39;,&#39;A&#39;..&#39;Z&#39;,&#39;a&#39;..&#39;z&#39;,&#39;&#43;&#39;,&#39;/&#39;,&#39;&#61;&#39;]) then
begin
Dec(IdxEnd);
if Idx < IdxEnd then
Move(InBuf[Idx&#43;1], InBuf[Idx], IdxEnd-Idx);
WhiteFound :&#61; True;
end
else
Inc(Idx);
end;
until (not WhiteFound) or (EndReached);
Result :&#61; IdxEnd;
end;
begin
repeat
SkipWhite;
BytesRead :&#61; ReadInput;
InBufPtr :&#61; InBuf;
OutBufPtr :&#61; &#64;OutBuf;
I :&#61; 0;
while I < BytesRead do
begin
Packet :&#61; DecodePacket(InBufPtr, J);
K :&#61; 0;
while J > 0 do
begin
OutBufPtr^ :&#61; AnsiChar(Packet.a[K]);
Inc(OutBufPtr);
Dec(J);
Inc(K);
end;
Inc(InBufPtr, 4);
Inc(I, 4);
end;
Output.Write(OutBuf, OutBufPtr - PAnsiChar(&#64;OutBuf));
until BytesRead &#61; 0;
end;
function EncodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr :&#61; TStringStream.Create(Input);
try
OutStr :&#61; TStringStream.Create(&#39;&#39;);
try
EncodeStream(InStr, OutStr);
Result :&#61; OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
function DecodeString(const Input: string): string;
var
InStr, OutStr: TStringStream;
begin
InStr :&#61; TStringStream.Create(Input);
try
OutStr :&#61; TStringStream.Create(&#39;&#39;);
try
DecodeStream(InStr, OutStr);
Result :&#61; OutStr.DataString;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
constructor TPointerStream.Create(P: Pointer; Size: Integer);
begin
SetPointer(P, Size);
end;
function TPointerStream.Write(const Buffer; Count: Longint): Longint;
var
Pos, EndPos, Size: Longint;
Mem: Pointer;
begin
Pos :&#61; Self.Position;
if (Pos >&#61; 0) and (Count > 0) then
begin
EndPos :&#61; Pos &#43; Count;
Size:&#61; Self.Size;
if EndPos > Size then
raise EStreamError.CreateRes(&#64;SMemoryStreamError);
Mem :&#61; Self.Memory;
System.Move(Buffer, Pointer(Longint(Mem) &#43; Pos)^, Count);
Self.Position :&#61; Pos;
Result :&#61; Count;
Exit;
end;
Result :&#61; 0;
end;
function DecodeBase64(const Input: AnsiString): TBytes;
var
InStr: TPointerStream;
OutStr: TBytesStream;
Len: Integer;
begin
InStr :&#61; TPointerStream.Create(PAnsiChar(Input), Length(Input));
try
OutStr :&#61; TBytesStream.Create;
try
DecodeStream(InStr, OutStr);
Result :&#61; OutStr.Bytes;
Len :&#61; OutStr.Size;
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
SetLength(Result, Len);
end;
function EncodeBase64(const Input: Pointer; Size: Integer): AnsiString;
var
InStr: TPointerStream;
OutStr: TBytesStream;
begin
InStr :&#61; TPointerStream.Create(Input, Size);
try
OutStr :&#61; TBytesStream.Create;
try
EncodeStream(InStr, OutStr);
SetString(Result, PAnsiChar(OutStr.Memory), OutStr.Size);
finally
OutStr.Free;
end;
finally
InStr.Free;
end;
end;
end.