lasarus_compotents/gecko/nsStream.pas

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.