+ Patch to support sizeless streams by Sebastian Guenter

This commit is contained in:
michael 1999-08-13 16:31:41 +00:00
parent 54baf96873
commit 4f4354e276
3 changed files with 87 additions and 39 deletions

View File

@ -32,15 +32,18 @@ type
TBase64DecodingStream = class(TStream)
protected
InputStream: TStream;
CurPos, DataLen: LongInt;
CurPos, InputStreamSize: LongInt;
Buf: array[0..2] of Byte;
BufPos: Integer; // Offset of byte which is to be read next
fEOF: Boolean;
public
constructor Create(AInputStream: TStream);
procedure Reset;
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
property EOF: Boolean read fEOF;
end;
@ -153,25 +156,17 @@ end;
constructor TBase64DecodingStream.Create(AInputStream: TStream);
var
ipos: LongInt;
endbytes: array[0..1] of Char;
begin
inherited Create;
InputStream := AInputStream;
Reset;
end;
procedure TBase64DecodingStream.Reset;
begin
InputStreamSize := -1;
BufPos := 3;
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;
fEOF := False;
end;
function TBase64DecodingStream.Read(var Buffer; Count: Longint): Longint;
@ -179,36 +174,62 @@ var
p: PChar;
b: Char;
ReadBuf: array[0..3] of Byte;
ToRead, ReadOK, i, j: Integer;
ToRead, OrgToRead, HaveRead, ReadOK, i, j: Integer;
begin
if Count <= 0 then exit(0);
if CurPos + Count > DataLen then
Count := DataLen - CurPos;
if Count <= 0 then exit(0);
if InputStreamSize <> -1 then begin
if CurPos + Count > InputStreamSize then
Count := InputStreamSize - CurPos;
if Count <= 0 then exit(0);
end;
Result := Count;
Result := 0;
p := PChar(@Buffer);
while Count > 0 do begin
while (Count > 0) and not fEOF do begin
if BufPos > 2 then begin
BufPos := 0;
// Read the next 4 valid bytes
ToRead := 4;
ReadOK := 0;
while ToRead > 0 do begin
InputStream.Read(ReadBuf[ReadOK], ToRead);
i := ReadOk;
while i <= 3 do begin
ReadBuf[i] := DecTable[ReadBuf[i]];
if ReadBuf[i] = 99 then begin
for j := i to 3 do
ReadBuf[i] := ReadBuf[i + 1];
end else begin
Inc(i);
Inc(ReadOK);
Dec(ToRead);
OrgToRead := ToRead;
HaveRead := InputStream.Read(ReadBuf[ReadOK], ToRead);
//WriteLn('ToRead = ', ToRead, ', HaveRead = ', HaveRead, ', ReadOK=', ReadOk);
if HaveRead > 0 then begin
i := ReadOk;
while i <= HaveRead do begin
ReadBuf[i] := DecTable[ReadBuf[i]];
if ReadBuf[i] = 99 then
for j := i to 3 do
ReadBuf[i] := ReadBuf[i + 1]
else begin
Inc(i);
Inc(ReadOK);
Dec(ToRead);
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[1] := (ReadBuf[1] and 15) shl 4 or ReadBuf[2] shr 2;
Buf[2] := (ReadBuf[2] and 3) shl 6 or ReadBuf[3];
@ -219,6 +240,7 @@ begin
Inc(BufPos);
Inc(CurPos);
Dec(Count);
Inc(Result);
end;
end;
@ -228,12 +250,31 @@ begin
end;
function TBase64DecodingStream.Seek(Offset: Longint; Origin: Word): Longint;
var
ipos: LongInt;
endbytes: array[0..1] of Char;
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
if (Origin = soFromCurrent) and (Offset = 0) then
Result := CurPos
else if (Origin = soFromEnd) and (Offset = 0) then
Result := DataLen
Result := InputStreamSize
else if (Origin = soFromBeginning) and (Offset = CurPos) then
Result := CurPos
else
@ -246,7 +287,10 @@ end.
{
$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
Revision 1.1 1999/08/03 17:02:38 michael

View File

@ -31,4 +31,4 @@ tidea.pp test program for IDEA encryption/decryption streams (MVC)
b64test.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)
b64dec.pp base64-decodes file given as 1st argument to StdOut (SG)
b64dec.pp base64-decodes StdIn to StdOut (SG)

View File

@ -1,6 +1,6 @@
// $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
{$MODE objfpc}
@ -13,10 +13,11 @@ var
IsEnd: Boolean;
begin
InputStream := TFileStream.Create(ParamStr(1), fmOpenRead);
InputStream := THandleStream.Create(StdInputHandle);
b64decoder := TBase64DecodingStream.Create(InputStream);
IsEnd := False;
while not IsEnd do
try
Write(Chr(b64decoder.ReadByte));
@ -31,7 +32,10 @@ end.
{
$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
}