mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 23:09:18 +02:00
+ Patch to support sizeless streams by Sebastian Guenter
This commit is contained in:
parent
54baf96873
commit
4f4354e276
@ -32,15 +32,18 @@ type
|
|||||||
TBase64DecodingStream = class(TStream)
|
TBase64DecodingStream = class(TStream)
|
||||||
protected
|
protected
|
||||||
InputStream: TStream;
|
InputStream: TStream;
|
||||||
CurPos, DataLen: LongInt;
|
CurPos, InputStreamSize: LongInt;
|
||||||
Buf: array[0..2] of Byte;
|
Buf: array[0..2] of Byte;
|
||||||
BufPos: Integer; // Offset of byte which is to be read next
|
BufPos: Integer; // Offset of byte which is to be read next
|
||||||
|
fEOF: Boolean;
|
||||||
public
|
public
|
||||||
constructor Create(AInputStream: TStream);
|
constructor Create(AInputStream: TStream);
|
||||||
|
procedure Reset;
|
||||||
|
|
||||||
function Read(var Buffer; Count: Longint): Longint; override;
|
function Read(var Buffer; Count: Longint): Longint; override;
|
||||||
function Write(const Buffer; Count: Longint): Longint; override;
|
function Write(const Buffer; Count: Longint): Longint; override;
|
||||||
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
function Seek(Offset: Longint; Origin: Word): Longint; override;
|
||||||
|
property EOF: Boolean read fEOF;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -153,25 +156,17 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
constructor TBase64DecodingStream.Create(AInputStream: TStream);
|
constructor TBase64DecodingStream.Create(AInputStream: TStream);
|
||||||
var
|
|
||||||
ipos: LongInt;
|
|
||||||
endbytes: array[0..1] of Char;
|
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
InputStream := AInputStream;
|
InputStream := AInputStream;
|
||||||
|
Reset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBase64DecodingStream.Reset;
|
||||||
|
begin
|
||||||
|
InputStreamSize := -1;
|
||||||
BufPos := 3;
|
BufPos := 3;
|
||||||
|
fEOF := False;
|
||||||
ipos := InputStream.Position;
|
|
||||||
DataLen := ((InputStream.Size - ipos + 3) div 4) * 3;
|
|
||||||
InputStream.Seek(-2, soFromEnd);
|
|
||||||
InputStream.Read(endbytes, 2);
|
|
||||||
InputStream.Position := ipos;
|
|
||||||
|
|
||||||
if endbytes[1] = '=' then begin
|
|
||||||
Dec(DataLen);
|
|
||||||
if endbytes[0] = '=' then
|
|
||||||
Dec(DataLen);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TBase64DecodingStream.Read(var Buffer; Count: Longint): Longint;
|
function TBase64DecodingStream.Read(var Buffer; Count: Longint): Longint;
|
||||||
@ -179,36 +174,62 @@ var
|
|||||||
p: PChar;
|
p: PChar;
|
||||||
b: Char;
|
b: Char;
|
||||||
ReadBuf: array[0..3] of Byte;
|
ReadBuf: array[0..3] of Byte;
|
||||||
ToRead, ReadOK, i, j: Integer;
|
ToRead, OrgToRead, HaveRead, ReadOK, i, j: Integer;
|
||||||
begin
|
begin
|
||||||
if Count <= 0 then exit(0);
|
if Count <= 0 then exit(0);
|
||||||
if CurPos + Count > DataLen then
|
if InputStreamSize <> -1 then begin
|
||||||
Count := DataLen - CurPos;
|
if CurPos + Count > InputStreamSize then
|
||||||
|
Count := InputStreamSize - CurPos;
|
||||||
if Count <= 0 then exit(0);
|
if Count <= 0 then exit(0);
|
||||||
|
end;
|
||||||
|
|
||||||
Result := Count;
|
Result := 0;
|
||||||
p := PChar(@Buffer);
|
p := PChar(@Buffer);
|
||||||
while Count > 0 do begin
|
while (Count > 0) and not fEOF do begin
|
||||||
if BufPos > 2 then begin
|
if BufPos > 2 then begin
|
||||||
BufPos := 0;
|
BufPos := 0;
|
||||||
// Read the next 4 valid bytes
|
// Read the next 4 valid bytes
|
||||||
ToRead := 4;
|
ToRead := 4;
|
||||||
ReadOK := 0;
|
ReadOK := 0;
|
||||||
while ToRead > 0 do begin
|
while ToRead > 0 do begin
|
||||||
InputStream.Read(ReadBuf[ReadOK], ToRead);
|
OrgToRead := ToRead;
|
||||||
|
HaveRead := InputStream.Read(ReadBuf[ReadOK], ToRead);
|
||||||
|
//WriteLn('ToRead = ', ToRead, ', HaveRead = ', HaveRead, ', ReadOK=', ReadOk);
|
||||||
|
if HaveRead > 0 then begin
|
||||||
i := ReadOk;
|
i := ReadOk;
|
||||||
while i <= 3 do begin
|
while i <= HaveRead do begin
|
||||||
ReadBuf[i] := DecTable[ReadBuf[i]];
|
ReadBuf[i] := DecTable[ReadBuf[i]];
|
||||||
if ReadBuf[i] = 99 then begin
|
if ReadBuf[i] = 99 then
|
||||||
for j := i to 3 do
|
for j := i to 3 do
|
||||||
ReadBuf[i] := ReadBuf[i + 1];
|
ReadBuf[i] := ReadBuf[i + 1]
|
||||||
end else begin
|
else begin
|
||||||
Inc(i);
|
Inc(i);
|
||||||
Inc(ReadOK);
|
Inc(ReadOK);
|
||||||
Dec(ToRead);
|
Dec(ToRead);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
if HaveRead <> OrgToRead then begin
|
||||||
|
//WriteLn('Ende? ReadOK=', ReadOK, ', count=', Count);
|
||||||
|
for i := ReadOK to 3 do
|
||||||
|
ReadBuf[i] := Ord('=');
|
||||||
|
fEOF := True;
|
||||||
|
if ReadOK < 2 then exit; // Not enough data available in input stream
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Check for fill bytes
|
||||||
|
if (Count >= 2) and (ReadBuf[3] = Ord('=')) then begin
|
||||||
|
//WriteLn('Endemarkierung!');
|
||||||
|
fEOF := True;
|
||||||
|
if ReadBuf[2] = Ord('=') then
|
||||||
|
Count := 1
|
||||||
|
else
|
||||||
|
Count := 2;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Decode the 4 bytes in the buffer to 3 undecoded bytes
|
||||||
Buf[0] := ReadBuf[0] shl 2 or ReadBuf[1] shr 4;
|
Buf[0] := ReadBuf[0] shl 2 or ReadBuf[1] shr 4;
|
||||||
Buf[1] := (ReadBuf[1] and 15) shl 4 or ReadBuf[2] shr 2;
|
Buf[1] := (ReadBuf[1] and 15) shl 4 or ReadBuf[2] shr 2;
|
||||||
Buf[2] := (ReadBuf[2] and 3) shl 6 or ReadBuf[3];
|
Buf[2] := (ReadBuf[2] and 3) shl 6 or ReadBuf[3];
|
||||||
@ -219,6 +240,7 @@ begin
|
|||||||
Inc(BufPos);
|
Inc(BufPos);
|
||||||
Inc(CurPos);
|
Inc(CurPos);
|
||||||
Dec(Count);
|
Dec(Count);
|
||||||
|
Inc(Result);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -228,12 +250,31 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
function TBase64DecodingStream.Seek(Offset: Longint; Origin: Word): Longint;
|
function TBase64DecodingStream.Seek(Offset: Longint; Origin: Word): Longint;
|
||||||
|
var
|
||||||
|
ipos: LongInt;
|
||||||
|
endbytes: array[0..1] of Char;
|
||||||
begin
|
begin
|
||||||
|
{This will work only if the input stream supports seeking / Size. If not, the
|
||||||
|
input stream will raise an exception; we don't handle them here but pass them
|
||||||
|
to the caller.}
|
||||||
|
if InputStreamSize = -1 then begin
|
||||||
|
ipos := InputStream.Position;
|
||||||
|
InputStreamSize := ((InputStream.Size - ipos + 3) div 4) * 3;
|
||||||
|
InputStream.Seek(-2, soFromEnd);
|
||||||
|
InputStream.Read(endbytes, 2);
|
||||||
|
InputStream.Position := ipos;
|
||||||
|
if endbytes[1] = '=' then begin
|
||||||
|
Dec(InputStreamSize);
|
||||||
|
if endbytes[0] = '=' then
|
||||||
|
Dec(InputStreamSize);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// This stream only supports the Seek modes needed for determining its size
|
// This stream only supports the Seek modes needed for determining its size
|
||||||
if (Origin = soFromCurrent) and (Offset = 0) then
|
if (Origin = soFromCurrent) and (Offset = 0) then
|
||||||
Result := CurPos
|
Result := CurPos
|
||||||
else if (Origin = soFromEnd) and (Offset = 0) then
|
else if (Origin = soFromEnd) and (Offset = 0) then
|
||||||
Result := DataLen
|
Result := InputStreamSize
|
||||||
else if (Origin = soFromBeginning) and (Offset = CurPos) then
|
else if (Origin = soFromBeginning) and (Offset = CurPos) then
|
||||||
Result := CurPos
|
Result := CurPos
|
||||||
else
|
else
|
||||||
@ -246,7 +287,10 @@ end.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.2 1999-08-09 16:12:28 michael
|
Revision 1.3 1999-08-13 16:31:41 michael
|
||||||
|
+ Patch to support sizeless streams by Sebastian Guenter
|
||||||
|
|
||||||
|
Revision 1.2 1999/08/09 16:12:28 michael
|
||||||
* Fixes and new examples from Sebastian Guenther
|
* Fixes and new examples from Sebastian Guenther
|
||||||
|
|
||||||
Revision 1.1 1999/08/03 17:02:38 michael
|
Revision 1.1 1999/08/03 17:02:38 michael
|
||||||
|
@ -31,4 +31,4 @@ tidea.pp test program for IDEA encryption/decryption streams (MVC)
|
|||||||
b64test.pp test program for base64 encoding streams (SG)
|
b64test.pp test program for base64 encoding streams (SG)
|
||||||
b64test2.pp test program for base64 encoding streams (SG)
|
b64test2.pp test program for base64 encoding streams (SG)
|
||||||
b64enc.pp base64-encodes StdIn to StdOut (SG)
|
b64enc.pp base64-encodes StdIn to StdOut (SG)
|
||||||
b64dec.pp base64-decodes file given as 1st argument to StdOut (SG)
|
b64dec.pp base64-decodes StdIn to StdOut (SG)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
// base64-decodes a file (argument #1) and writes the output to StdOut
|
// base64-decodes data from StdIn and writes the output to StdOut
|
||||||
// (c) 1999 Sebastian Guenther
|
// (c) 1999 Sebastian Guenther
|
||||||
|
|
||||||
{$MODE objfpc}
|
{$MODE objfpc}
|
||||||
@ -13,10 +13,11 @@ var
|
|||||||
IsEnd: Boolean;
|
IsEnd: Boolean;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
InputStream := TFileStream.Create(ParamStr(1), fmOpenRead);
|
InputStream := THandleStream.Create(StdInputHandle);
|
||||||
|
|
||||||
b64decoder := TBase64DecodingStream.Create(InputStream);
|
b64decoder := TBase64DecodingStream.Create(InputStream);
|
||||||
|
|
||||||
|
IsEnd := False;
|
||||||
while not IsEnd do
|
while not IsEnd do
|
||||||
try
|
try
|
||||||
Write(Chr(b64decoder.ReadByte));
|
Write(Chr(b64decoder.ReadByte));
|
||||||
@ -31,7 +32,10 @@ end.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.1 1999-08-09 16:12:26 michael
|
Revision 1.2 1999-08-13 16:31:43 michael
|
||||||
|
+ Patch to support sizeless streams by Sebastian Guenter
|
||||||
|
|
||||||
|
Revision 1.1 1999/08/09 16:12:26 michael
|
||||||
* Fixes and new examples from Sebastian Guenther
|
* Fixes and new examples from Sebastian Guenther
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user