402 lines
10 KiB
ObjectPascal
402 lines
10 KiB
ObjectPascal
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corpotation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Takanori Itou <necottie@nesitive.net>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
unit nsStream;
|
|
|
|
interface
|
|
|
|
uses
|
|
nsXPCOM, Classes,nsTypes;
|
|
|
|
function NS_NewByteArrayInputStream(out stream: nsIInputStream; const Buffer: Pointer; Size: Longword): nsresult;
|
|
function NS_NewInputStreamFromTStream(input: TStream; own: Boolean=False): nsIInputStream;
|
|
function NS_NewOutputStreamFromTStream(output: TStream; own: Boolean=False): nsIOutputStream;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math, nsMemory, nsError, SysUtils;
|
|
|
|
type
|
|
nsByteArrayInputStream = class(TInterfacedObject,
|
|
nsIInputStream)
|
|
FBuffer: PByte;
|
|
FNBytes: Longword;
|
|
FPos: Longword;
|
|
|
|
constructor Create(const Buffer: Pointer; nBytes: Longword);
|
|
destructor Destroy; override;
|
|
|
|
procedure Close(); safecall;
|
|
function Available(): PRUint32; safecall;
|
|
function Read(aBuf: PAnsiChar; aCount: Longword): PRUint32; safecall;
|
|
function ReadSegments(aWriter: nsWriteSegmentFun; aClosure: Pointer; aCount: Longword): PRUint32; safecall;
|
|
function IsNonBlocking(): PRBool; safecall;
|
|
end;
|
|
|
|
constructor nsByteArrayInputStream.Create(const Buffer: Pointer; nBytes: Longword);
|
|
begin
|
|
inherited Create;
|
|
FBuffer := PByte(Buffer);
|
|
FNBytes := nBytes;
|
|
FPos := 0;
|
|
end;
|
|
|
|
destructor nsByteArrayInputStream.Destroy;
|
|
begin
|
|
if Assigned(FBuffer) then
|
|
nsMemory.Free(FBuffer);
|
|
inherited;
|
|
end;
|
|
|
|
function nsByteArrayInputStream.Available(): PRUint32;
|
|
begin
|
|
if (FNBytes=0) or not Assigned(FBuffer) then
|
|
Result := 0
|
|
else
|
|
Result := FNBytes - FPos;
|
|
end;
|
|
|
|
procedure CopyMemory(var ADst; const ASrc; ASize: Integer); register; forward;
|
|
|
|
function nsByteArrayInputStream.Read(aBuf: PAnsiChar;
|
|
aCount: Longword): PRUint32;
|
|
begin
|
|
if (aCount=0) or (FPos = FNBytes) then
|
|
Result := 0
|
|
else
|
|
begin
|
|
Assert(Assigned(FBuffer), 'Stream buffer has been released - there''s an ownership problem somewhere!');
|
|
if not Assigned(FBuffer) then
|
|
Result := 0
|
|
else
|
|
if aCount > (FNBytes - FPos) then
|
|
begin
|
|
Result := FNBytes - FPos;
|
|
CopyMemory(aBuf^, FBuffer^, Result);
|
|
FPos := FNBytes;
|
|
end else
|
|
begin
|
|
Result := aCount;
|
|
CopyMemory(aBuf^, FBuffer^, Result);
|
|
Inc(FPos, aCount);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function nsByteArrayInputStream.ReadSegments(aWriter: nsWriteSegmentFun;
|
|
aClosure: Pointer;
|
|
aCount: Longword): PRUint32;
|
|
var
|
|
readCount: Longword;
|
|
rv: Longword;
|
|
newPtr: PByte;
|
|
begin
|
|
if FNBytes=0 then
|
|
raise EInvalidArgument.Create('nsIInputStream.ReadSegments');
|
|
|
|
if (aCount=0) or (FNBytes = FPos) then
|
|
Result := 0
|
|
else
|
|
begin
|
|
Assert(Assigned(FBuffer), 'Stream buffer has been released - there''s an ownership problem somewhere!');
|
|
readCount := Min(aCount, FNBytes - FPos);
|
|
if not Assigned(FBuffer) then
|
|
Result := 0
|
|
else
|
|
begin
|
|
newPtr := FBuffer;
|
|
Inc(newPtr, FPos);
|
|
rv := aWriter(Self, aClosure, PChar(newPtr), FPos, readCount, Result);
|
|
if NS_SUCCEEDED(rv) then
|
|
Inc(FPos, readCount);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function nsByteArrayInputStream.IsNonBlocking(): PRBool;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
procedure nsByteArrayInputStream.Close;
|
|
begin
|
|
if Assigned(FBuffer) then
|
|
begin
|
|
nsMemory.Free(FBuffer);
|
|
FBuffer := nil;
|
|
FNBytes := 0;
|
|
end else
|
|
raise Exception.Create('nsIInputStream.Close')
|
|
end;
|
|
|
|
function NS_NewByteArrayInputStream(out stream: nsIInputStream; const Buffer: Pointer; Size: Longword): nsresult;
|
|
begin
|
|
try
|
|
stream := nsByteArrayInputStream.Create(Buffer, Size);
|
|
except
|
|
Result := NS_ERROR_OUT_OF_MEMORY;
|
|
Exit;
|
|
end;
|
|
|
|
Result := NS_OK;
|
|
end;
|
|
|
|
type
|
|
TInputStream = class(TInterfacedObject,
|
|
nsIInputStream)
|
|
FStream: TStream;
|
|
FOwn: Boolean;
|
|
constructor Create(stream: TStream; own: Boolean);
|
|
destructor Destroy; override;
|
|
|
|
// nsIInputStream
|
|
procedure Close(); safecall;
|
|
function Available(): PRUint32; safecall;
|
|
function Read(aBuf: PAnsiChar; aCount: PRUint32): PRUint32; safecall;
|
|
function ReadSegments(aWriter: nsWriteSegmentFun; aClosure: Pointer; aCount: PRUint32): PRUint32; safecall;
|
|
function IsNonBlocking(): PRBool; safecall;
|
|
end;
|
|
|
|
constructor TInputStream.Create(stream: TStream; own: Boolean);
|
|
begin
|
|
inherited Create;
|
|
FStream := stream;
|
|
FOwn := own;
|
|
end;
|
|
|
|
destructor TInputStream.Destroy;
|
|
begin
|
|
if FOwn then
|
|
FStream.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TInputStream.Close;
|
|
begin
|
|
if FOwn then
|
|
begin
|
|
FStream.Free;
|
|
FOwn := False;
|
|
end;
|
|
FStream := nil;
|
|
end;
|
|
|
|
function TInputStream.Available: PRUint32;
|
|
var
|
|
size, pos: Int64;
|
|
begin
|
|
size := FStream.Size;
|
|
pos := FStream.Position;
|
|
if size>0 then
|
|
begin
|
|
Result := PRUint32(size-pos);
|
|
end else
|
|
begin
|
|
Result := High(PRUint32);
|
|
end;
|
|
end;
|
|
|
|
function TInputStream.Read(aBuf: PAnsiChar; aCount: PRUint32): PRUint32;
|
|
begin
|
|
Result := FStream.Read(aBuf^, aCount);
|
|
end;
|
|
|
|
function TInputStream.ReadSegments(aWriter: nsWriteSegmentFun;
|
|
aClosure: Pointer; aCount: PRUint32): PRUint32;
|
|
type
|
|
nsWriteSegmentFunc = function (aInStream: nsIInputStream;
|
|
aClosure: Pointer;
|
|
const aFromSegment: Pointer;
|
|
aToOffset: PRUint32;
|
|
aCount: PRUint32
|
|
): PRUint32; safecall;
|
|
|
|
var
|
|
data: Pointer;
|
|
begin
|
|
data := nsMemory.Alloc(aCount);
|
|
try
|
|
aCount := FStream.Read(data^, aCount);
|
|
Result := nsWriteSegmentFunc(aWriter)(
|
|
Self, aClosure, data, FStream.Position, aCount);
|
|
finally
|
|
nsMemory.Free(data);
|
|
end;
|
|
end;
|
|
|
|
function TInputStream.IsNonBlocking: PRBool;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function NS_NewInputStreamFromTStream(input: TStream; own: Boolean): nsIInputStream;
|
|
begin
|
|
Result := TInputStream.Create(input, own);
|
|
end;
|
|
|
|
type
|
|
TOutputStream = class(TInterfacedObject,
|
|
nsIOutputStream)
|
|
FStream: TStream;
|
|
FOwn: Boolean;
|
|
|
|
constructor Create(output: TStream; own: Boolean);
|
|
destructor Destroy; override;
|
|
|
|
procedure Close(); safecall;
|
|
procedure Flush(); safecall;
|
|
function Write(const aBuf: PAnsiChar; aCount: PRUint32): PRUint32; safecall;
|
|
function WriteFrom(aFromStream: nsIInputStream; aCount: PRUint32): PRUint32; safecall;
|
|
function WriteSegments(aReader: nsReadSegmentFun; aClosure: Pointer; aCount: PRUint32): PRUint32; safecall;
|
|
function IsNonBlocking(): PRBool; safecall;
|
|
end;
|
|
|
|
constructor TOutputStream.Create(output: TStream; own: Boolean);
|
|
begin
|
|
inherited Create;
|
|
FStream := output;
|
|
FOwn := own;
|
|
end;
|
|
|
|
destructor TOutputStream.Destroy;
|
|
begin
|
|
if FOwn then
|
|
FStream.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TOutputStream.Close;
|
|
begin
|
|
if FOwn then
|
|
begin
|
|
FStream.Free;
|
|
FOwn := False;
|
|
end;
|
|
FStream := nil;
|
|
end;
|
|
|
|
procedure TOutputStream.Flush;
|
|
begin
|
|
end;
|
|
|
|
function TOutputStream.Write(const aBuf: PAnsiChar; aCount: PRUint32): PRUint32;
|
|
begin
|
|
Result := FStream.Write(aBuf^, aCount);
|
|
end;
|
|
|
|
function TOutputStream.WriteFrom(aFromStream: nsIInputStream; aCount: PRUint32): PRUint32;
|
|
var
|
|
data: Pointer;
|
|
begin
|
|
data := nsMemory.Alloc(aCount);
|
|
try
|
|
aCount := aFromStream.Read(data, aCount);
|
|
Result := FStream.Write(data^, aCount);
|
|
finally
|
|
nsMemory.Free(data);
|
|
end;
|
|
end;
|
|
|
|
function TOutputStream.WriteSegments(aReader: nsReadSegmentFun;
|
|
aClosure: Pointer; aCount: PRUint32): PRUint32;
|
|
type
|
|
nsReadSegmentFunc = function (aOutStream: nsIOutputStream;
|
|
aClosure: Pointer;
|
|
aToSegment: Pointer;
|
|
aFromOffset: PRUint32;
|
|
aCount: PRUint32
|
|
): PRUint32; safecall;
|
|
var
|
|
data: Pointer;
|
|
begin
|
|
data := nsMemory.Alloc(aCount);
|
|
try
|
|
aCount := nsReadSegmentFunc(aReader)
|
|
(Self, aClosure, data, FStream.Position, aCount);
|
|
Result := FStream.Write(data^, aCount);
|
|
finally
|
|
nsMemory.Free(data);
|
|
end;
|
|
end;
|
|
|
|
function TOutputStream.IsNonBlocking: PRBool;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
function NS_NewOutputStreamFromTStream(output: TStream; own: Boolean): nsIOutputStream;
|
|
begin
|
|
Result := TOutputStream.Create(output, own);
|
|
end;
|
|
|
|
|
|
{$IFDEF CPU386} //Should be defined with both Delphi and Intel FPC.
|
|
procedure CopyMemory(var ADst; const ASrc; ASize: Integer);
|
|
asm
|
|
push edi
|
|
push esi
|
|
pushf
|
|
|
|
mov edi, eax
|
|
mov esi, edx
|
|
mov edx, ecx
|
|
shr ecx, 2
|
|
cld
|
|
test ecx, ecx
|
|
jz @@no4
|
|
|
|
rep movsd
|
|
@@no4:
|
|
and edx, 3
|
|
test edx, edx
|
|
jz @@no1
|
|
mov ecx, edx
|
|
rep movsb
|
|
@@no1:
|
|
popf
|
|
pop esi
|
|
pop edi
|
|
end;
|
|
{$ELSE}
|
|
procedure CopyMemory(var ADst; const ASrc; ASize: Integer);
|
|
begin
|
|
Move(ASrc, ADst, ASize);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
end.
|