mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 11:49:23 +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)
|
||||
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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user