{
IOStream – модуль для создания потоков ввода-вывода.
Copyright © 2017 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit IOStream;
{$MODE DELPHI,EXTENDEDSYNTAX ON}
interface
uses
Lang;
{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}
type
Connection = interface;
Input = interface;
Output = interface;
DataInput = interface;
DataOutput = interface;
InputStream = class;
OutputStream = class;
InputOutputStream = class;
DataInputStream = class;
DataOutputStream = class;
ByteArrayStream = class;
IOException = class;
EOFException = class;
ReadOnlyStreamException = class;
WriteOnlyStreamException = class;
UTFDataFormatException = class;
Connection = interface(_Interface) ['{570879EA-220D-4569-904F-2C84ED0F5BAD}']
procedure close();
end;
Input = interface(Connection) ['{4F945778-9735-4045-9D2B-262E7DBCA406}']
function seekSupported(): boolean;
function seek(delta: long): long;
function size(): long;
function position(): long;
function available(): long;
function read(): int; overload;
function read(const dst: byte_Array1d): int; overload;
function read(const dst: byte_Array1d; offset, length: int): int; overload;
end;
Output = interface(Connection) ['{4D190AE0-CB0A-4081-AFD4-73CA4FBBBDC5}']
procedure flush();
function write(value: int): boolean; overload;
function write(const src: byte_Array1d): int; overload;
function write(const src: byte_Array1d; offset, length: int): int; overload;
end;
DataInput = interface(Input) ['{F7D51944-D8D6-4FF9-B53F-1C351F76AFE5}']
function readBoolean(): boolean;
function readChar(): char;
function readUChar(): uchar;
function readUCharLE(): uchar;
function readByte(): int;
function readShort(): int;
function readShortLE(): int;
function readInt(): int;
function readIntLE(): int;
function readLong(): long;
function readLongLE(): long;
function readUltra(): ultra;
function readUltraLE(): ultra;
function readFloat(): real;
function readFloatLE(): real;
function readDouble(): real;
function readDoubleLE(): real;
function readReal(): real;
function readRealLE(): real;
function readXVector(): xvector;
function readXVectorLE(): xvector;
function readUnsignedByte(): int;
function readUnsignedShort(): int;
function readUnsignedShortLE(): int;
function readString(): String;
function readUTF(): UnicodeString;
function readUTF16(): UnicodeString;
procedure readFully(const dst: byte_Array1d); overload;
procedure readFully(const dst: byte_Array1d; offset, length: int); overload;
procedure skipBytes(count: int);
end;
DataOutput = interface(Output) ['{44EBF7E6-0A8A-4B5A-BF68-1C84441D883C}']
procedure writeBoolean(const data: boolean);
procedure writeChar(const data: char);
procedure writeUChar(const data: uchar);
procedure writeUCharLE(const data: uchar);
procedure writeByte(const data: int);
procedure writeShort(const data: int);
procedure writeShortLE(const data: int);
procedure writeInt(const data: int);
procedure writeIntLE(const data: int);
procedure writeLong(const data: long);
procedure writeLongLE(const data: long);
procedure writeUltra(const data: ultra);
procedure writeUltraLE(const data: ultra);
procedure writeFloat(const data: real);
procedure writeFloatLE(const data: real);
procedure writeDouble(const data: real);
procedure writeDoubleLE(const data: real);
procedure writeReal(const data: real);
procedure writeRealLE(const data: real);
procedure writeXVector(const data: xvector);
procedure writeXVectorLE(const data: xvector);
procedure writeString(const data: String);
procedure writeUTF(const data: UnicodeString);
procedure writeUTF16(const data: UnicodeString);
procedure writeFully(const src: byte_Array1d); overload;
procedure writeFully(const src: byte_Array1d; offset, length: int); overload;
end;
InputStream = class(RefCountInterfacedObject, Connection, Input)
public
constructor create();
procedure close(); virtual;
function seekSupported(): boolean; virtual;
function seek(delta: long): long; virtual;
function size(): long; virtual; abstract;
function position(): long; virtual; abstract;
function available(): long; virtual;
function read(): int; overload; virtual; abstract;
function read(const dst: byte_Array1d): int; overload; virtual;
function read(const dst: byte_Array1d; offset, length: int): int; overload; virtual;
end;
OutputStream = class(RefCountInterfacedObject, Connection, Output)
public
constructor create();
procedure close(); virtual;
procedure flush(); virtual;
function write(value: int): boolean; overload; virtual; abstract;
function write(const src: byte_Array1d): int; overload; virtual;
function write(const src: byte_Array1d; offset, length: int): int; overload; virtual;
end;
InputOutputStream = class(RefCountInterfacedObject, Connection, Input, Output)
public
constructor create();
procedure close(); virtual;
procedure flush(); virtual;
function seekSupported(): boolean; virtual;
function seek(delta: long): long; virtual;
function size(): long; virtual; abstract;
function position(): long; virtual; abstract;
function available(): long; virtual;
function read(): int; overload; virtual; abstract;
function read(const dst: byte_Array1d): int; overload; virtual;
function read(const dst: byte_Array1d; offset, length: int): int; overload; virtual;
function write(value: int): boolean; overload; virtual; abstract;
function write(const src: byte_Array1d): int; overload; virtual;
function write(const src: byte_Array1d; offset, length: int): int; overload; virtual;
function readAllowed(): boolean; virtual;
function writeAllowed(): boolean; virtual;
procedure truncate(); virtual; abstract;
end;
DataInputStream = class(InputStream, DataInput)
public
constructor create(inp: Input);
procedure close(); override;
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function size(): long; override;
function position(): long; override;
function available(): long; override;
function read(): int; overload; override; final;
function read(const dst: byte_Array1d): int; overload; override; final;
function read(const dst: byte_Array1d;
offset, length: int): int; overload; override; final;
function readBoolean(): boolean;
function readChar(): char;
function readUChar(): uchar;
function readUCharLE(): uchar;
function readByte(): int;
function readShort(): int;
function readShortLE(): int;
function readInt(): int;
function readIntLE(): int;
function readLong(): long;
function readLongLE(): long;
function readUltra(): ultra;
function readUltraLE(): ultra;
function readFloat(): real;
function readFloatLE(): real;
function readDouble(): real;
function readDoubleLE(): real;
function readReal(): real;
function readRealLE(): real;
function readXVector(): xvector;
function readXVectorLE(): xvector;
function readUnsignedByte(): int;
function readUnsignedShort(): int;
function readUnsignedShortLE(): int;
function readString(): String;
function readUTF(): UnicodeString;
function readUTF16(): UnicodeString;
procedure readFully(const dst: byte_Array1d); overload;
procedure readFully(const dst: byte_Array1d; offset, length: int); overload;
procedure skipBytes(count: int);
protected
inp: Input;
end;
DataOutputStream = class(OutputStream, DataOutput)
public
constructor create(outp: Output);
procedure close(); override;
procedure flush(); override;
function write(value: int): boolean; overload; override; final;
function write(const src: byte_Array1d): int; overload; override; final;
function write(const src: byte_Array1d;
offset, length: int): int; overload; override; final;
procedure writeBoolean(const data: boolean);
procedure writeChar(const data: char);
procedure writeUChar(const data: uchar);
procedure writeUCharLE(const data: uchar);
procedure writeByte(const data: int);
procedure writeShort(const data: int);
procedure writeShortLE(const data: int);
procedure writeInt(const data: int);
procedure writeIntLE(const data: int);
procedure writeLong(const data: long);
procedure writeLongLE(const data: long);
procedure writeUltra(const data: ultra);
procedure writeUltraLE(const data: ultra);
procedure writeFloat(const data: real);
procedure writeFloatLE(const data: real);
procedure writeDouble(const data: real);
procedure writeDoubleLE(const data: real);
procedure writeReal(const data: real);
procedure writeRealLE(const data: real);
procedure writexVector(const data: xvector);
procedure writeXVectorLE(const data: xvector);
procedure writeString(const data: String);
procedure writeUTF(const data: UnicodeString);
procedure writeUTF16(const data: UnicodeString);
procedure writeFully(const src: byte_Array1d); overload;
procedure writeFully(const src: byte_Array1d; offset, length: int); overload;
protected
outp: Output;
end;
ByteArrayStream = class(InputOutputStream)
public
constructor create(); overload;
constructor create(const buf: byte_Array1d; size: int); overload;
constructor create(const src: byte_Array1d; offset, length: int); overload;
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function size(): long; override;
function position(): long; override;
function available(): long; override;
function read(): int; overload; override;
function read(const dst: byte_Array1d; offset, length: int): int; overload; override;
function write(value: int): boolean; overload; override;
function write(const src: byte_Array1d; offset, length: int): int; overload; override;
function writeAllowed(): boolean; override;
function toString(): AnsiString; override;
procedure truncate(); override;
function toByteArray(): byte_Array1d; virtual;
strict private
writable: boolean;
start: int;
finish: int;
offset: int;
buf: byte_Array1d;
end;
IOException = class(Exception);
EOFException = class(IOException);
ReadOnlyStreamException = class(IOException);
WriteOnlyStreamException = class(IOException);
UTFDataFormatException = class(IOException);
resourcestring
msgUTFDataFormat = 'Ошибка в UTF-данных.';
msgUTFTooLong = 'Размер UTF-данных не может превышать 64 КБ.';
msgEndOfStreamReached = 'Достигнут конец потока ввода-вывода.';
msgReadOnlyStream = 'Поток ввода-вывода доступен только для чтения.';
msgWriteOnlyStream = 'Поток ввода-вывода доступен только для записи.';
msgSeekNotSupported = 'Произвольное позиционирование не поддерживается';
implementation
{ InputStream }
constructor InputStream.create();
begin
inherited create();
end;
procedure InputStream.close();
begin
end;
function InputStream.seekSupported(): boolean;
begin
result := false;
end;
function InputStream.seek(delta: long): long;
begin
result := delta; { чтобы избежать сообщений компилятора. Этой строки не должно быть здесь. }
raise IOException.create(msgSeekNotSupported);
end;
function InputStream.available(): long;
var
p: long;
s: long;
begin
p := position();
s := size();
if (p >= 0) and (p <= s) then begin
result := s - p;
end else begin
result := -1;
end;
end;
function InputStream.read(const dst: byte_Array1d): int;
begin
result := read(dst, 0, length(dst));
end;
function InputStream.read(const dst: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
b: int;
i: int;
begin
lim := offset + length;
len := System.length(dst);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
for i := offset to lim - 1 do begin
b := read();
if b < 0 then begin
break;
end;
dst[i] := byte(b);
inc(result);
end;
end;
{ OutputStream }
constructor OutputStream.create();
begin
inherited create();
end;
procedure OutputStream.close();
begin
end;
procedure OutputStream.flush();
begin
end;
function OutputStream.write(const src: byte_Array1d): int;
begin
result := write(src, 0, length(src));
end;
function OutputStream.write(const src: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
i: int;
begin
lim := offset + length;
len := System.length(src);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
for i := offset to lim - 1 do begin
if write(src[i]) = false then begin
break;
end;
inc(result);
end;
end;
{ InputOutputStream }
constructor InputOutputStream.create();
begin
inherited create();
end;
procedure InputOutputStream.close();
begin
end;
procedure InputOutputStream.flush();
begin
end;
function InputOutputStream.seekSupported(): boolean;
begin
result := false;
end;
function InputOutputStream.seek(delta: long): long;
begin
result := delta; { чтобы избежать сообщений компилятора. Этой строки не должно быть здесь. }
raise IOException.create(msgSeekNotSupported);
end;
function InputOutputStream.available(): long;
var
p: long;
s: long;
begin
p := position();
s := size();
if (p >= 0) and (p <= s) then begin
result := s - p;
end else begin
result := -1;
end;
end;
function InputOutputStream.read(const dst: byte_Array1d): int;
begin
result := read(dst, 0, length(dst));
end;
function InputOutputStream.read(const dst: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
b: int;
i: int;
begin
lim := offset + length;
len := System.length(dst);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
for i := offset to lim - 1 do begin
b := read();
if b < 0 then begin
break;
end;
dst[i] := byte(b);
inc(result);
end;
end;
function InputOutputStream.write(const src: byte_Array1d): int;
begin
result := write(src, 0, length(src));
end;
function InputOutputStream.write(const src: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
i: int;
begin
lim := offset + length;
len := System.length(src);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
result := 0;
for i := offset to lim - 1 do begin
if write(src[i]) = false then begin
break;
end;
inc(result);
end;
end;
function InputOutputStream.readAllowed(): boolean;
begin
result := true;
end;
function InputOutputStream.writeAllowed(): boolean;
begin
result := true;
end;
{ DataInputStream }
constructor DataInputStream.create(inp: Input);
begin
inherited create();
self.inp := inp;
end;
procedure DataInputStream.close();
begin
inp.close();
end;
function DataInputStream.seekSupported(): boolean;
begin
result := inp.seekSupported();
end;
function DataInputStream.seek(delta: long): long;
begin
result := inp.seek(delta);
end;
function DataInputStream.size(): long;
begin
result := inp.size();
end;
function DataInputStream.position(): long;
begin
result := inp.position();
end;
function DataInputStream.available(): long;
begin
result := inp.available();
end;
function DataInputStream.read(): int;
begin
result := inp.read();
end;
function DataInputStream.read(const dst: byte_Array1d): int;
begin
result := inp.read(dst);
end;
function DataInputStream.read(const dst: byte_Array1d; offset, length: int): int;
begin
result := inp.read(dst, offset, length);
end;
function DataInputStream.readBoolean(): boolean;
begin
result := readUnsignedByte() > 0;
end;
function DataInputStream.readChar(): char;
begin
result := char(readUnsignedByte());
end;
function DataInputStream.readUChar(): uchar;
begin
result := uchar(readUnsignedShort());
end;
function DataInputStream.readUCharLE(): uchar;
begin
result := uchar(readUnsignedShortLE());
end;
function DataInputStream.readByte(): int;
begin
result := byte(readUnsignedByte());
end;
function DataInputStream.readShort(): int;
begin
result := short(readUnsignedShort());
end;
function DataInputStream.readShortLE(): int;
begin
result := short(readUnsignedShortLE());
end;
function DataInputStream.readInt(): int;
var
byte1: int;
byte2: int;
byte3: int;
byte4: int;
begin
byte1 := read();
byte2 := read();
byte3 := read();
byte4 := read();
if byte1 or byte2 or byte3 or byte4 < 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
result := (byte1 shl 24) or (byte2 shl 16) or (byte3 shl 8) or byte4;
end;
function DataInputStream.readIntLE(): int;
var
byte1: int;
byte2: int;
byte3: int;
byte4: int;
begin
byte1 := read();
byte2 := read();
byte3 := read();
byte4 := read();
if byte1 or byte2 or byte3 or byte4 < 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
result := byte1 or (byte2 shl 8) or (byte3 shl 16) or (byte4 shl 24);
end;
function DataInputStream.readLong(): long;
var
int1: int;
int2: int;
begin
int1 := readInt();
int2 := readInt();
result := longBuild(int1, int2);
end;
function DataInputStream.readLongLE(): long;
var
int1: int;
int2: int;
begin
int1 := readIntLE();
int2 := readIntLE();
result := longBuild(int2, int1);
end;
function DataInputStream.readUltra(): ultra;
var
int1: int;
int2: int;
int3: int;
int4: int;
begin
int1 := readInt();
int2 := readInt();
int3 := readInt();
int4 := readInt();
result := ultraBuild(longBuild(int1, int2), longBuild(int3, int4));
end;
function DataInputStream.readUltraLE(): ultra;
var
int1: int;
int2: int;
int3: int;
int4: int;
begin
int1 := readIntLE();
int2 := readIntLE();
int3 := readIntLE();
int4 := readIntLE();
result := ultraBuild(longBuild(int4, int3), longBuild(int2, int1));
end;
function DataInputStream.readFloat(): real;
begin
result := intBitsToFloat(readInt());
end;
function DataInputStream.readFloatLE(): real;
begin
result := intBitsToFloat(readIntLE());
end;
function DataInputStream.readDouble(): real;
begin
result := longBitsToDouble(readLong());
end;
function DataInputStream.readDoubleLE(): real;
begin
result := longBitsToDouble(readLongLE());
end;
function DataInputStream.readReal(): real;
var
exponent: int;
significand: long;
begin
exponent := readUnsignedShort();
significand := readLong();
result := realBuild(exponent, significand);
end;
function DataInputStream.readRealLE(): real;
var
exponent: int;
significand: long;
begin
significand := readLongLE();
exponent := readUnsignedShortLE();
result := realBuild(exponent, significand);
end;
function DataInputStream.readXVector(): xvector;
var
float1: float;
float2: float;
float3: float;
float4: float;
begin
float1 := readFloat();
float2 := readFloat();
float3 := readFloat();
float4 := readFloat();
result := xvectorBuild(float1, float2, float3, float4);
end;
function DataInputStream.readXVectorLE(): xvector;
var
float1: float;
float2: float;
float3: float;
float4: float;
begin
float1 := readFloatLE();
float2 := readFloatLE();
float3 := readFloatLE();
float4 := readFloatLE();
result := xvectorBuild(float4, float3, float2, float1);
end;
function DataInputStream.readUnsignedByte(): int;
var
byte1: int;
begin
byte1 := read();
if byte1 < 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
result := byte1;
end;
function DataInputStream.readUnsignedShort(): int;
var
byte1: int;
byte2: int;
begin
byte1 := read();
byte2 := read();
if byte1 or byte2 < 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
result := (byte1 shl 8) or byte2;
end;
function DataInputStream.readUnsignedShortLE(): int;
var
byte1: int;
byte2: int;
begin
byte1 := read();
byte2 := read();
if byte1 or byte2 < 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
result := byte1 or (byte2 shl 8);
end;
function DataInputStream.readString(): String;
var
len: int;
buf: byte_Array1d;
begin
len := readUnsignedShort();
if len = 0 then begin
result := '';
exit;
end;
buf := byte_Array1d_create(len);
readFully(buf);
result := String_create(buf, 0, len);
end;
function DataInputStream.readUTF(): UnicodeString;
var
i: int;
b1: int;
b2: int;
b3: int;
slen: int;
rlen: int;
buf: uchar_Array1d;
b: byte_Array1d;
begin
slen := readUnsignedShort();
if slen = 0 then begin
result := '';
exit;
end;
i := 0;
rlen := 0;
buf := uchar_Array1d_create(slen);
b := byte_Array1d_create(slen);
readFully(b);
while i < slen do begin
b1 := b[i] and $ff;
case b1 shr 4 of
$00..$07: begin
inc(i);
buf[rlen] := uchar(b1);
inc(rlen);
end;
$0c..$0d: begin
inc(i, 2);
if i <= slen then begin
b2 := b[i - 1];
if b2 and $c0 <> $80 then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end else begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
buf[rlen] := uchar(((b1 and $1f) shl 6) or (b2 and $3f));
inc(rlen);
end;
$0e: begin
inc(i, 3);
if i <= slen then begin
b2 := b[i - 2];
b3 := b[i - 1];
if (b2 and $c0 <> $80) or (b3 and $c0 <> $80) then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end else begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
buf[rlen] := uchar(((b1 and $0f) shl 12) or ((b2 and $3f) shl 6) or (b3 and $3f));
inc(rlen);
end;
else
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end;
result := UnicodeString_create(buf, 0, rlen);
end;
function DataInputStream.readUTF16(): UnicodeString;
var
i: int;
b1: int;
b2: int;
b3: int;
b4: int;
code: int;
slen: int;
rlen: int;
buf: uchar_Array1d;
b: byte_Array1d;
begin
slen := readUnsignedShort();
if slen = 0 then begin
result := '';
exit;
end;
i := 0;
rlen := 0;
buf := uchar_Array1d_create(slen);
b := byte_Array1d_create(slen);
readFully(b);
while i < slen do begin
b1 := b[i] and $ff;
case b1 of
$00..$7f: begin
inc(i);
buf[rlen] := uchar(b1);
inc(rlen);
end;
$c0..$df: begin
inc(i, 2);
if i <= slen then begin
b2 := b[i - 1];
if b2 and $c0 <> $80 then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end else begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
buf[rlen] := uchar(((b1 and $1f) shl 6) or (b2 and $3f));
inc(rlen);
end;
$e0..$ef: begin
inc(i, 3);
if i <= slen then begin
b2 := b[i - 2];
b3 := b[i - 1];
if (b2 and $c0 <> $80) or (b3 and $c0 <> $80) then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end else begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
code := ((b1 and $0f) shl 12) or ((b2 and $3f) shl 6) or (b3 and $3f);
if (code >= $d800) and (code < $e000) then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
buf[rlen] := uchar(code);
inc(rlen);
end;
$f0..$f7: begin
inc(i, 4);
if i <= slen then begin
b2 := b[i - 3];
b3 := b[i - 2];
b4 := b[i - 1];
if (b2 and $c0 <> $80) or (b3 and $c0 <> $80) or (b4 and $c0 <> $80) then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end else begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
code := ((b1 and $07) shl 18) or ((b2 and $3f) shl 12) or
((b3 and $3f) shl 6) or (b4 and $3f);
if (code < $00d800) or (code >= $00e000) and (code < $010000) then begin
buf[rlen] := uchar(code);
inc(rlen);
end else
if (code >= $010000) and (code < $110000) then begin
code := code - $010000;
buf[rlen] := uchar($d800 or (code shr 10));
inc(rlen);
buf[rlen] := uchar($dc00 or (code and $03ff));
inc(rlen);
end else begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end;
else
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
end;
result := UnicodeString_create(buf, 0, rlen);
end;
procedure DataInputStream.readFully(const dst: byte_Array1d);
begin
readFully(dst, 0, length(dst));
end;
procedure DataInputStream.readFully(const dst: byte_Array1d; offset, length: int);
var
lim: int;
len: int;
c: int;
p: int;
begin
lim := offset + length;
len := System.length(dst);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
p := 0;
while p < length do begin
c := read(dst, offset + p, length - p);
if c <= 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
inc(p, c);
end;
end;
procedure DataInputStream.skipBytes(count: int);
var
sp: long;
np: long;
begin
if count <= 0 then begin
exit;
end;
if seekSupported() then begin
sp := position();
repeat
np := seek(long(count));
if sp >= np then begin
raise EOFException.create(msgEndOfStreamReached);
end;
dec(count, int(np - sp));
sp := np;
until count <= 0;
end else begin
repeat
if read() < 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
dec(count);
until count <= 0;
end;
end;
{ DataOutputStream }
constructor DataOutputStream.create(outp: Output);
begin
inherited create();
self.outp := outp;
end;
procedure DataOutputStream.close();
begin
outp.close();
end;
procedure DataOutputStream.flush();
begin
outp.flush();
end;
function DataOutputStream.write(value: int): boolean;
begin
result := outp.write(value);
end;
function DataOutputStream.write(const src: byte_Array1d): int;
begin
result := outp.write(src);
end;
function DataOutputStream.write(const src: byte_Array1d; offset, length: int): int;
begin
result := outp.write(src, offset, length);
end;
procedure DataOutputStream.writeBoolean(const data: boolean);
begin
if data = true then begin
writeByte($01);
end else begin
writeByte($00);
end;
end;
procedure DataOutputStream.writeChar(const data: char);
begin
writeByte(int(data));
end;
procedure DataOutputStream.writeUChar(const data: uchar);
begin
writeByte(int(data) shr 8);
writeByte(int(data));
end;
procedure DataOutputStream.writeUCharLE(const data: uchar);
begin
writeByte(int(data));
writeByte(int(data) shr 8);
end;
procedure DataOutputStream.writeByte(const data: int);
begin
if write(data) = false then begin
raise EOFException.create(msgEndOfStreamReached);
end;
end;
procedure DataOutputStream.writeShort(const data: int);
begin
writeByte(data shr 8);
writeByte(data);
end;
procedure DataOutputStream.writeShortLE(const data: int);
begin
writeByte(data);
writeByte(data shr 8);
end;
procedure DataOutputStream.writeInt(const data: int);
begin
writeByte(data shr $18);
writeByte(data shr $10);
writeByte(data shr $08);
writeByte(data);
end;
procedure DataOutputStream.writeIntLE(const data: int);
begin
writeByte(data);
writeByte(data shr $08);
writeByte(data shr $10);
writeByte(data shr $18);
end;
procedure DataOutputStream.writeLong(const data: long);
begin
writeByte(int(data shr $38));
writeByte(int(data shr $30));
writeByte(int(data shr $28));
writeByte(int(data shr $20));
writeByte(int(data shr $18));
writeByte(int(data shr $10));
writeByte(int(data shr $08));
writeByte(int(data));
end;
procedure DataOutputStream.writeLongLE(const data: long);
begin
writeByte(int(data));
writeByte(int(data shr $08));
writeByte(int(data shr $10));
writeByte(int(data shr $18));
writeByte(int(data shr $20));
writeByte(int(data shr $28));
writeByte(int(data shr $30));
writeByte(int(data shr $38));
end;
procedure DataOutputStream.writeUltra(const data: ultra);
begin
writeLong(data.longs[1]);
writeLong(data.longs[0]);
end;
procedure DataOutputStream.writeUltraLE(const data: ultra);
begin
writeLongLE(data.longs[0]);
writeLongLE(data.longs[1]);
end;
procedure DataOutputStream.writeFloat(const data: real);
begin
writeInt(floatToIntBits(realToFloat(data)));
end;
procedure DataOutputStream.writeFloatLE(const data: real);
begin
writeIntLE(floatToIntBits(realToFloat(data)));
end;
procedure DataOutputStream.writeDouble(const data: real);
begin
writeLong(doubleToLongBits(realToDouble(data)));
end;
procedure DataOutputStream.writeDoubleLE(const data: real);
begin
writeLongLE(doubleToLongBits(realToDouble(data)));
end;
procedure DataOutputStream.writeReal(const data: real);
begin
writeShort(realExtractExponent(data));
writeLong(realExtractSignificand(data));
end;
procedure DataOutputStream.writeRealLE(const data: real);
begin
writeLongLE(realExtractSignificand(data));
writeShortLE(realExtractExponent(data));
end;
procedure DataOutputStream.writeXVector(const data: xvector);
begin
writeFloat(data.floats[3]);
writeFloat(data.floats[2]);
writeFloat(data.floats[1]);
writeFloat(data.floats[0]);
end;
procedure DataOutputStream.writeXVectorLE(const data: xvector);
begin
writeFloatLE(data.floats[0]);
writeFloatLE(data.floats[1]);
writeFloatLE(data.floats[2]);
writeFloatLE(data.floats[3]);
end;
procedure DataOutputStream.writeString(const data: String);
var
len: int;
begin
len := length(data);
if (len < 0) or (len >= $00010000) then begin
raise UTFDataFormatException.create(msgUTFTooLong);
end;
writeShort(len);
writeFully(stringToByteArray(data), 0, len);
end;
procedure DataOutputStream.writeUTF(const data: UnicodeString);
var
i: int;
code: int;
slen: int;
rlen: int;
buf: uchar_Array1d;
res: byte_Array1d;
begin
buf := stringToCharArray(data);
slen := length(buf);
rlen := 0;
for i := 0 to slen - 1 do begin
code := int(buf[i]);
if (code >= $0001) and (code < $0080) then begin
inc(rlen);
end else
if code < $0800 then begin
inc(rlen, 2);
end else begin
inc(rlen, 3);
end;
end;
if rlen >= $00010000 then begin
raise UTFDataFormatException.create(msgUTFTooLong);
end;
res := byte_Array1d_create(rlen);
rlen := 0;
for i := 0 to slen - 1 do begin
code := int(buf[i]);
if (code >= $0001) and (code < $0080) then begin
res[rlen] := byte(code);
inc(rlen);
end else
if code < $0800 then begin
res[rlen] := byte($c0 or ((code shr 6) and $1f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end else begin
res[rlen] := byte($e0 or ((code shr 12) and $0f));
inc(rlen);
res[rlen] := byte($80 or ((code shr 6) and $3f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end;
end;
writeShort(rlen);
writeFully(res, 0, rlen);
end;
procedure DataOutputStream.writeUTF16(const data: UnicodeString);
var
i: int;
code: int;
surr: int;
slen: int;
rlen: int;
buf: uchar_Array1d;
res: byte_Array1d;
begin
buf := stringToCharArray(data);
slen := length(buf);
rlen := 0;
i := 0;
while i < slen do begin
code := int(buf[i]);
if (code >= $0001) and (code < $0080) then begin
inc(rlen);
end else
if code < $0800 then begin
inc(rlen, 2);
end else
if (code < $d800) or (code >= $e000) then begin
inc(rlen, 3);
end else begin
inc(i);
if i = slen then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
surr := int(buf[i]);
if (surr < $dc00) or (surr >= $e000) then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
code := ((code and $03ff) shl 10) + (surr and $03ff) + $010000;
if (code >= $000001) and (code < $000080) then begin
inc(rlen);
end else
if code < $000800 then begin
inc(rlen, 2);
end else
if code < $010000 then begin
inc(rlen, 3);
end else begin
inc(rlen, 4);
end;
end;
inc(i);
end;
if rlen >= $00010000 then begin
raise UTFDataFormatException.create(msgUTFTooLong);
end;
res := byte_Array1d_create(rlen);
rlen := 0;
i := 0;
while i < slen do begin
code := int(buf[i]);
if (code >= $0001) and (code < $0080) then begin
res[rlen] := byte(code);
inc(rlen);
end else
if code < $0800 then begin
res[rlen] := byte($c0 or ((code shr 6) and $1f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end else
if (code < $d800) or (code >= $e000) then begin
res[rlen] := byte($e0 or ((code shr 12) and $0f));
inc(rlen);
res[rlen] := byte($80 or ((code shr 6) and $3f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end else begin
inc(i);
if i = slen then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
surr := int(buf[i]);
if (surr < $dc00) or (surr >= $e000) then begin
raise UTFDataFormatException.create(msgUTFDataFormat);
end;
code := ((code and $03ff) shl 10) + (surr and $03ff) + $010000;
if (code >= $000001) and (code < $000080) then begin
res[rlen] := byte(code);
inc(rlen);
end else
if code < $000800 then begin
res[rlen] := byte($c0 or ((code shr 6) and $1f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end else
if code < $010000 then begin
res[rlen] := byte($e0 or ((code shr 12) and $0f));
inc(rlen);
res[rlen] := byte($80 or ((code shr 6) and $3f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end else begin
res[rlen] := byte($f0 or ((code shr 18) and $07));
inc(rlen);
res[rlen] := byte($80 or ((code shr 12) and $3f));
inc(rlen);
res[rlen] := byte($80 or ((code shr 6) and $3f));
inc(rlen);
res[rlen] := byte($80 or (code and $3f));
inc(rlen);
end;
end;
inc(i);
end;
writeShort(rlen);
writeFully(res, 0, rlen);
end;
procedure DataOutputStream.writeFully(const src: byte_Array1d);
begin
writeFully(src, 0, length(src));
end;
procedure DataOutputStream.writeFully(const src: byte_Array1d; offset, length: int);
var
lim: int;
len: int;
c: int;
p: int;
begin
lim := offset + length;
len := System.length(src);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
p := 0;
while p < length do begin
c := write(src, offset + p, length - p);
if c <= 0 then begin
raise EOFException.create(msgEndOfStreamReached);
end;
inc(p, c);
end;
end;
{ ByteArrayStream }
constructor ByteArrayStream.create();
begin
inherited create();
self.writable := true;
self.start := 0;
self.finish := 0;
self.offset := 0;
self.buf := byte_Array1d_create(32);
end;
constructor ByteArrayStream.create(const buf: byte_Array1d; size: int);
begin
inherited create();
self.writable := true;
self.start := 0;
self.finish := Math.max(0, Math.min(length(buf), size));
self.offset := 0;
self.buf := buf;
end;
constructor ByteArrayStream.create(const src: byte_Array1d; offset, length: int);
var
len: int;
start: int;
begin
inherited create();
len := System.length(src);
start := Math.max(0, Math.min(len, offset));
self.writable := false;
self.start := start;
self.finish := Math.max(start, Math.min(len, offset + length));
self.offset := start;
self.buf := src;
end;
function ByteArrayStream.seekSupported(): boolean;
begin
result := true;
end;
function ByteArrayStream.seek(delta: long): long;
var
start: int;
offset: int;
realDelta: int;
begin
start := self.start;
offset := self.offset;
if delta < 0 then begin
realDelta := int(Math.max(long(start) - long(offset), delta));
end else begin
realDelta := int(Math.min(long(finish) - long(offset), delta));
end;
inc(offset, realDelta);
self.offset := offset;
result := long(offset) - long(start);
end;
function ByteArrayStream.size(): long;
begin
result := long(finish) - long(start);
end;
function ByteArrayStream.position(): long;
begin
result := long(offset) - long(start);
end;
function ByteArrayStream.available(): long;
begin
result := long(finish) - long(offset);
end;
function ByteArrayStream.read(): int;
var
offset: int;
begin
offset := self.offset;
if offset >= finish then begin
result := -1;
exit;
end;
result := buf[offset] and $ff;
self.offset := offset + 1;
end;
function ByteArrayStream.read(const dst: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
bufofs: int;
begin
lim := offset + length;
len := System.length(dst);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
bufofs := self.offset;
result := Math.min(finish - bufofs, length);
self.offset := bufofs + result;
arraycopyPrimitives(buf, bufofs, dst, offset, result);
end;
function ByteArrayStream.write(value: int): boolean;
var
newlen: int;
finish: int;
bufofs: int;
buflen: int;
buf: byte_Array1d;
newbuf: byte_Array1d;
begin
if not writable then begin
raise ReadOnlyStreamException.create(msgReadOnlyStream);
end;
buf := self.buf;
finish := self.finish;
bufofs := self.offset;
buflen := length(buf);
newlen := bufofs + 1;
if buflen < newlen then begin
newlen := Math.max(buflen shl 1, newlen);
newbuf := byte_Array1d_create(newlen);
arraycopyPrimitives(buf, 0, newbuf, 0, finish);
buf := newbuf;
self.buf := newbuf;
end;
buf[bufofs] := byte(value);
inc(bufofs);
if finish < bufofs then begin
finish := bufofs;
end;
self.finish := finish;
self.offset := bufofs;
result := true;
end;
function ByteArrayStream.write(const src: byte_Array1d; offset, length: int): int;
var
lim: int;
len: int;
newlen: int;
finish: int;
bufofs: int;
buflen: int;
buf: byte_Array1d;
newbuf: byte_Array1d;
begin
if not writable then begin
raise ReadOnlyStreamException.create(msgReadOnlyStream);
end;
lim := offset + length;
len := System.length(src);
if (lim > len) or (lim < offset) or (offset > len) or (offset < 0) then begin
raise ArrayIndexOutOfBoundsException.create(msgArrayIndexOutOfBounds);
end;
buf := self.buf;
finish := self.finish;
bufofs := self.offset;
buflen := System.length(buf);
newlen := bufofs + length;
if buflen < newlen then begin
newlen := Math.max(buflen shl 1, newlen);
newbuf := byte_Array1d_create(newlen);
arraycopyPrimitives(buf, 0, newbuf, 0, finish);
buf := newbuf;
self.buf := newbuf;
end;
arraycopyPrimitives(src, offset, buf, bufofs, length);
inc(bufofs, length);
if finish < bufofs then begin
finish := bufofs;
end;
self.finish := finish;
self.offset := bufofs;
result := length;
end;
function ByteArrayStream.writeAllowed(): boolean;
begin
result := writable;
end;
function ByteArrayStream.toString(): AnsiString;
var
start: int;
begin
start := self.start;
result := String_create(buf, start, finish - start);
end;
procedure ByteArrayStream.truncate();
begin
if not writable then begin
raise ReadOnlyStreamException.create(msgReadOnlyStream);
end;
finish := offset;
end;
function ByteArrayStream.toByteArray(): byte_Array1d;
var
len: int;
start: int;
begin
start := self.start;
len := finish - start;
result := byte_Array1d_create(len);
arraycopyPrimitives(buf, start, result, 0, len);
end;
end.