{
pascalx.io — модуль базового ввода-вывода.
Copyright © 2021 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit pascalx.io;
{$MODE DELPHI}
interface
uses
pascalx.lang;
{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}
{%region public }
type
Closeable = interface;
Input = interface;
DataInput = interface;
Output = interface;
DataOutput = interface;
InputStream = class;
OutputStream = class;
IOStream = class;
DataInputStream = class;
DataOutputStream = class;
ByteArrayInputStream = class;
ByteArrayOutputStream = class;
ByteArrayIOStream = class;
IOException = class;
EOFException = class;
UTFDataFormatException = class;
Closeable = interface(_Interface) ['{74C86B60-AC5B-4E8D-8ACD-29A50B5C1500}']
procedure close();
end;
Input = interface(Closeable) ['{74C86B60-AC5B-4E8D-8ACD-29A50B5C1501}']
function seekSupported(): boolean;
function seek(delta: long): long;
function reset(position: long = 0): long;
function position(): long;
function available(): long;
function size(): 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;
DataInput = interface(Input) ['{74C86B60-AC5B-4E8D-8ACD-29A50B5C1502}']
function skipBytes(count: int): int;
function readBoolean(): boolean;
function readChar(): char;
function readWChar(): wchar;
function readByte(): int;
function readShort(): int;
function readInt(): int;
function readLong(): long;
function readFloat(): float;
function readDouble(): double;
function readReal(): real;
function readUnsignedByte(): int;
function readUnsignedShort(): int;
function readWCharLE(): wchar;
function readShortLE(): int;
function readIntLE(): int;
function readLongLE(): long;
function readFloatLE(): float;
function readDoubleLE(): double;
function readRealLE(): real;
function readUnsignedShortLE(): int;
function readUTF(): UnicodeString;
procedure readFully(const dst: byte_Array1d); overload;
procedure readFully(const dst: byte_Array1d; offset, length: int); overload;
end;
Output = interface(Closeable) ['{74C86B60-AC5B-4E8D-8ACD-29A50B5C1503}']
procedure flush();
procedure write(data: int); overload;
procedure write(const src: byte_Array1d); overload;
procedure write(const src: byte_Array1d; offset, length: int); overload;
end;
DataOutput = interface(Output) ['{74C86B60-AC5B-4E8D-8ACD-29A50B5C1504}']
procedure writeBoolean(data: boolean);
procedure writeChar(data: char);
procedure writeWChar(data: wchar);
procedure writeByte(data: int);
procedure writeShort(data: int);
procedure writeInt(data: int);
procedure writeLong(data: long);
procedure writeFloat(data: float);
procedure writeDouble(data: double);
procedure writeReal(const data: real);
procedure writeWCharLE(data: wchar);
procedure writeShortLE(data: int);
procedure writeIntLE(data: int);
procedure writeLongLE(data: long);
procedure writeFloatLE(data: float);
procedure writeDoubleLE(data: double);
procedure writeRealLE(const data: real);
procedure writeUTF(const data: UnicodeString);
procedure writeAnsiChars(const data: AnsiString);
procedure writeUnicodeChars(const data: UnicodeString);
procedure writeUnicodeCharsLE(const data: UnicodeString);
end;
InputStream = class(RefCountInterfacedObject, Closeable, Input)
public
function seekSupported(): boolean; virtual;
function seek(delta: long): long; virtual;
function reset(position: long = 0): long; virtual;
function position(): long; virtual;
function available(): long; virtual;
function size(): long; virtual;
function read(): int; virtual; abstract; overload;
function read(const dst: byte_Array1d): int; virtual; overload;
function read(const dst: byte_Array1d; offset, length: int): int; virtual; overload;
procedure close(); virtual;
end;
OutputStream = class(RefCountInterfacedObject, Closeable, Output)
public
procedure flush(); virtual;
procedure write(data: int); virtual; abstract; overload;
procedure write(const src: byte_Array1d); virtual; overload;
procedure write(const src: byte_Array1d; offset, length: int); virtual; overload;
procedure close(); virtual;
end;
IOStream = class(_Object, Closeable)
public
function seekSupported(): boolean; virtual;
function truncateSupported(): boolean; virtual;
function seek(delta: long): long; virtual;
function reset(position: long = 0): long; virtual;
function position(): long; virtual;
function truncate(): long; virtual;
function getInputStream(): InputStream; virtual; abstract;
function getOutputStream(): OutputStream; virtual; abstract;
procedure close(); virtual;
end;
DataInputStream = class(InputStream, DataInput)
protected
stream: Input;
public
constructor create(stream: Input);
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function reset(position: long = 0): long; override;
function position(): long; override;
function available(): long; override;
function size(): long; override;
function read(): int; override; overload;
function read(const dst: byte_Array1d): int; override; overload;
function read(const dst: byte_Array1d; offset, length: int): int; override; overload;
function skipBytes(count: int): int;
function readBoolean(): boolean;
function readChar(): char;
function readWChar(): wchar;
function readByte(): int;
function readShort(): int;
function readInt(): int;
function readLong(): long;
function readFloat(): float;
function readDouble(): double;
function readReal(): real;
function readUnsignedByte(): int;
function readUnsignedShort(): int;
function readWCharLE(): wchar;
function readShortLE(): int;
function readIntLE(): int;
function readLongLE(): long;
function readFloatLE(): float;
function readDoubleLE(): double;
function readRealLE(): real;
function readUnsignedShortLE(): int;
function readUTF(): UnicodeString;
procedure readFully(const dst: byte_Array1d); overload;
procedure readFully(const dst: byte_Array1d; offset, length: int); overload;
procedure close(); override;
end;
DataOutputStream = class(OutputStream, DataOutput)
protected
stream: Output;
public
constructor create(stream: Output);
procedure flush(); override;
procedure write(data: int); override; overload;
procedure write(const src: byte_Array1d); override; overload;
procedure write(const src: byte_Array1d; offset, length: int); override; overload;
procedure writeBoolean(data: boolean);
procedure writeChar(data: char);
procedure writeWChar(data: wchar);
procedure writeByte(data: int);
procedure writeShort(data: int);
procedure writeInt(data: int);
procedure writeLong(data: long);
procedure writeFloat(data: float);
procedure writeDouble(data: double);
procedure writeReal(const data: real);
procedure writeWCharLE(data: wchar);
procedure writeShortLE(data: int);
procedure writeIntLE(data: int);
procedure writeLongLE(data: long);
procedure writeFloatLE(data: float);
procedure writeDoubleLE(data: double);
procedure writeRealLE(const data: real);
procedure writeUTF(const data: UnicodeString);
procedure writeAnsiChars(const data: AnsiString);
procedure writeUnicodeChars(const data: UnicodeString);
procedure writeUnicodeCharsLE(const data: UnicodeString);
procedure close(); override;
end;
ByteArrayInputStream = class(InputStream)
protected
offset: int;
buffer: byte_Array1d;
public
constructor create(const buffer: byte_Array1d; offset: int = 0);
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function reset(position: long = 0): long; override;
function position(): long; override;
function available(): long; override;
function size(): long; override;
function read(): int; override; overload;
function read(const dst: byte_Array1d; offset, length: int): int; override; overload;
end;
ByteArrayOutputStream = class(OutputStream)
protected
offset: int;
buffer: byte_Array1d;
public
constructor create(initialCapacity: int = 0);
function toString(): AnsiString; override;
function toByteArray(): byte_Array1d; virtual;
function size(): int; virtual;
procedure reset(); virtual;
procedure write(data: int); override; overload;
procedure write(const src: byte_Array1d; offset, length: int); override; overload;
end;
ByteArrayIOStream = class(IOStream)
private
inputPos: int;
inputPtr: InputStream;
inputIntf: Input;
outputPos: int;
outputPtr: OutputStream;
outputIntf: Output;
bufferSize: int;
buffer: byte_Array1d;
public
constructor create(initialCapacity: int = 0); overload;
constructor create(const buffer: byte_Array1d; writePosition: int = 0; readPosition: int = 0); overload;
function toString(): AnsiString; override;
function toByteArray(): byte_Array1d; virtual;
function size(): int; virtual;
function seekSupported(): boolean; override;
function truncateSupported(): boolean; override;
function seek(delta: long): long; override;
function reset(position: long = 0): long; override;
function position(): long; override;
function truncate(): long; override;
function getInputStream(): InputStream; override;
function getOutputStream(): OutputStream; override;
procedure close(); override;
end;
IOException = class(Exception);
EOFException = class(IOException);
UTFDataFormatException = class(IOException);
resourcestring
msgTruncatingNotSupported = 'Обрезка не поддерживается';
msgPositioningNotSupported = 'Позиционирование не поддерживается';
msgEndOfStream = 'Достигнут конец потока данных';
msgArrayFull = 'Достигнут максимальный размер массива';
msgUTFDataTooLong = 'Размер данных, закодированных кодировкой UTF-8, не может превышать 65535 байт';
msgParentIOStreamClosed = 'Родительский поток данных закрыт';
{%endregion}
implementation
{%region private }
type
ByteArrayIOStream0InputStream = class;
ByteArrayIOStream0OutputStream = class;
ByteArrayIOStream0InputStream = class(InputStream)
private
owner: ByteArrayIOStream;
public
constructor create(owner: ByteArrayIOStream);
function seekSupported(): boolean; override;
function seek(delta: long): long; override;
function reset(position: long = 0): long; override;
function position(): long; override;
function available(): long; override;
function size(): long; override;
function read(): int; override; overload;
function read(const dst: byte_Array1d; offset, length: int): int; override; overload;
end;
ByteArrayIOStream0OutputStream = class(OutputStream)
private
owner: ByteArrayIOStream;
public
constructor create(owner: ByteArrayIOStream);
procedure write(data: int); override; overload;
procedure write(const src: byte_Array1d; offset, length: int); override; overload;
end;
{%endregion}
{%region InputStream }
function InputStream.seekSupported(): boolean;
begin
result := false;
end;
function InputStream.seek(delta: long): long;
var
i: long;
begin
if delta < 0 then begin
raise IOException.create('InputStream.seek: ' + msgPositioningNotSupported);
end;
for i := 0 to delta - 1 do begin
read();
end;
result := position();
end;
function InputStream.reset(position: long): long;
begin
raise IOException.create('InputStream.reset: ' + msgPositioningNotSupported);
end;
function InputStream.position(): long;
begin
result := 0;
end;
function InputStream.available(): long;
begin
result := 0;
end;
function InputStream.size(): long;
begin
result := 0;
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
readed: int;
begin
arrayCheckBounds('InputStream.read', system.length(dst), offset, length);
result := 0;
while result < length do begin
try
readed := read();
if readed < 0 then begin
if result = 0 then dec(result);
break;
end;
dst[offset] := byte(readed);
inc(offset);
except
on e: IOException do begin
if result > 0 then break;
raise;
end;
end;
inc(result);
end;
end;
procedure InputStream.close();
begin
end;
{%endregion}
{%region OutputStream }
procedure OutputStream.flush();
begin
end;
procedure OutputStream.write(const src: byte_Array1d);
begin
write(src, 0, length(src));
end;
procedure OutputStream.write(const src: byte_Array1d; offset, length: int);
begin
arrayCheckBounds('OutputStream.write', system.length(src), offset, length);
while length > 0 do begin
write(src[offset]);
inc(offset);
dec(length);
end;
end;
procedure OutputStream.close();
begin
end;
{%endregion}
{%region IOStream }
function IOStream.seekSupported(): boolean;
begin
result := false;
end;
function IOStream.truncateSupported(): boolean;
begin
result := false;
end;
function IOStream.seek(delta: long): long;
begin
raise IOException.create('IOStream.seek: ' + msgPositioningNotSupported);
end;
function IOStream.reset(position: long): long;
begin
raise IOException.create('IOStream.reset: ' + msgPositioningNotSupported);
end;
function IOStream.position(): long;
begin
result := seek(0);
end;
function IOStream.truncate(): long;
begin
raise IOException.create('IOStream.truncate: ' + msgTruncatingNotSupported);
end;
procedure IOStream.close();
begin
free();
end;
{%endregion}
{%region DataInputStream }
constructor DataInputStream.create(stream: Input);
begin
inherited create();
self.stream := stream;
end;
function DataInputStream.seekSupported(): boolean;
begin
result := stream.seekSupported();
end;
function DataInputStream.seek(delta: long): long;
begin
result := stream.seek(delta);
end;
function DataInputStream.reset(position: long): long;
begin
result := stream.reset(position);
end;
function DataInputStream.position(): long;
begin
result := stream.position();
end;
function DataInputStream.available(): long;
begin
result := stream.available();
end;
function DataInputStream.size(): long;
begin
result := stream.size();
end;
function DataInputStream.read(): int;
begin
result := stream.read();
end;
function DataInputStream.read(const dst: byte_Array1d): int;
begin
result := stream.read(dst);
end;
function DataInputStream.read(const dst: byte_Array1d; offset, length: int): int;
begin
result := stream.read(dst, offset, length);
end;
function DataInputStream.skipBytes(count: int): int;
var
skiped: int;
position: long;
stream: Input;
begin
stream := self.stream;
result := 0;
while count > 0 do begin
position := stream.position();
skiped := int(stream.seek(count) - position);
if skiped <= 0 then break;
inc(result, skiped);
dec(count, skiped);
end;
end;
function DataInputStream.readBoolean(): boolean;
var
data: int;
begin
data := stream.read();
if data < 0 then begin
raise EOFException.create('DataInputStream.readBoolean: ' + msgEndOfStream);
end;
result := (data and $ff) > 0;
end;
function DataInputStream.readChar(): char;
var
data: int;
begin
data := stream.read();
if data < 0 then begin
raise EOFException.create('DataInputStream.readChar: ' + msgEndOfStream);
end;
result := char(data);
end;
function DataInputStream.readWChar(): wchar;
var
b0: int;
b1: int;
stream: Input;
begin
stream := self.stream;
b1 := stream.read();
b0 := stream.read();
if (b0 or b1) < 0 then begin
raise EOFException.create('DataInputStream.readWChar: ' + msgEndOfStream);
end;
result := wchar((b1 shl 8) or (b0 and $ff));
end;
function DataInputStream.readByte(): int;
var
data: int;
begin
data := stream.read();
if data < 0 then begin
raise EOFException.create('DataInputStream.readByte: ' + msgEndOfStream);
end;
result := byte(data);
end;
function DataInputStream.readShort(): int;
var
b0: int;
b1: int;
stream: Input;
begin
stream := self.stream;
b1 := stream.read();
b0 := stream.read();
if (b0 or b1) < 0 then begin
raise EOFException.create('DataInputStream.readShort: ' + msgEndOfStream);
end;
result := short((b1 shl 8) or (b0 and $ff));
end;
function DataInputStream.readInt(): int;
var
b0: int;
b1: int;
b2: int;
b3: int;
stream: Input;
begin
stream := self.stream;
b3 := stream.read();
b2 := stream.read();
b1 := stream.read();
b0 := stream.read();
if (b0 or b1 or b2 or b3) < 0 then begin
raise EOFException.create('DataInputStream.readInt: ' + msgEndOfStream);
end;
result := (b3 shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff);
end;
function DataInputStream.readLong(): long;
var
b0: long;
b1: long;
b2: long;
b3: long;
b4: long;
b5: long;
b6: long;
b7: long;
stream: Input;
begin
stream := self.stream;
b7 := stream.read();
b6 := stream.read();
b5 := stream.read();
b4 := stream.read();
b3 := stream.read();
b2 := stream.read();
b1 := stream.read();
b0 := stream.read();
if (b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7) < 0 then begin
raise EOFException.create('DataInputStream.readLong: ' + msgEndOfStream);
end;
result := (b7 shl 56) or ((b6 and $ff) shl 48) or ((b5 and $ff) shl 40) or ((b4 and $ff) shl 32) or ((b3 and $ff) shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff);
end;
function DataInputStream.readFloat(): float;
var
b0: int;
b1: int;
b2: int;
b3: int;
stream: Input;
begin
stream := self.stream;
b3 := stream.read();
b2 := stream.read();
b1 := stream.read();
b0 := stream.read();
if (b0 or b1 or b2 or b3) < 0 then begin
raise EOFException.create('DataInputStream.readFloat: ' + msgEndOfStream);
end;
result := intBitsToFloat((b3 shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff));
end;
function DataInputStream.readDouble(): double;
var
b0: long;
b1: long;
b2: long;
b3: long;
b4: long;
b5: long;
b6: long;
b7: long;
stream: Input;
begin
stream := self.stream;
b7 := stream.read();
b6 := stream.read();
b5 := stream.read();
b4 := stream.read();
b3 := stream.read();
b2 := stream.read();
b1 := stream.read();
b0 := stream.read();
if (b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7) < 0 then begin
raise EOFException.create('DataInputStream.readDouble: ' + msgEndOfStream);
end;
result := longBitsToDouble((b7 shl 56) or ((b6 and $ff) shl 48) or ((b5 and $ff) shl 40) or ((b4 and $ff) shl 32) or ((b3 and $ff) shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff));
end;
function DataInputStream.readReal(): real;
var
a0: int;
a1: int;
b0: long;
b1: long;
b2: long;
b3: long;
b4: long;
b5: long;
b6: long;
b7: long;
stream: Input;
begin
stream := self.stream;
a1 := stream.read();
a0 := stream.read();
b7 := stream.read();
b6 := stream.read();
b5 := stream.read();
b4 := stream.read();
b3 := stream.read();
b2 := stream.read();
b1 := stream.read();
b0 := stream.read();
if (b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7 or long(a0) or long(a1)) < 0 then begin
raise EOFException.create('DataInputStream.readReal: ' + msgEndOfStream);
end;
a0 := (a1 shl 8) or (a0 and $ff);
b0 := (b7 shl 56) or ((b6 and $ff) shl 48) or ((b5 and $ff) shl 40) or ((b4 and $ff) shl 32) or ((b3 and $ff) shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff);
result := realBuild(a0, b0);
end;
function DataInputStream.readUnsignedByte(): int;
var
data: int;
begin
data := stream.read();
if data < 0 then begin
raise EOFException.create('DataInputStream.readUnsignedByte: ' + msgEndOfStream);
end;
result := data and $ff;
end;
function DataInputStream.readUnsignedShort(): int;
var
b0: int;
b1: int;
stream: Input;
begin
stream := self.stream;
b1 := stream.read();
b0 := stream.read();
if (b0 or b1) < 0 then begin
raise EOFException.create('DataInputStream.readUnsignedShort: ' + msgEndOfStream);
end;
result := ((b1 and $ff) shl 8) or (b0 and $ff);
end;
function DataInputStream.readWCharLE(): wchar;
var
b0: int;
b1: int;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
if (b0 or b1) < 0 then begin
raise EOFException.create('DataInputStream.readWCharLE: ' + msgEndOfStream);
end;
result := wchar((b1 shl 8) or (b0 and $ff));
end;
function DataInputStream.readShortLE(): int;
var
b0: int;
b1: int;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
if (b0 or b1) < 0 then begin
raise EOFException.create('DataInputStream.readShortLE: ' + msgEndOfStream);
end;
result := short((b1 shl 8) or (b0 and $ff));
end;
function DataInputStream.readIntLE(): int;
var
b0: int;
b1: int;
b2: int;
b3: int;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
b2 := stream.read();
b3 := stream.read();
if (b0 or b1 or b2 or b3) < 0 then begin
raise EOFException.create('DataInputStream.readIntLE: ' + msgEndOfStream);
end;
result := (b3 shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff);
end;
function DataInputStream.readLongLE(): long;
var
b0: long;
b1: long;
b2: long;
b3: long;
b4: long;
b5: long;
b6: long;
b7: long;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
b2 := stream.read();
b3 := stream.read();
b4 := stream.read();
b5 := stream.read();
b6 := stream.read();
b7 := stream.read();
if (b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7) < 0 then begin
raise EOFException.create('DataInputStream.readLongLE: ' + msgEndOfStream);
end;
result := (b7 shl 56) or ((b6 and $ff) shl 48) or ((b5 and $ff) shl 40) or ((b4 and $ff) shl 32) or ((b3 and $ff) shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff);
end;
function DataInputStream.readFloatLE(): float;
var
b0: int;
b1: int;
b2: int;
b3: int;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
b2 := stream.read();
b3 := stream.read();
if (b0 or b1 or b2 or b3) < 0 then begin
raise EOFException.create('DataInputStream.readFloatLE: ' + msgEndOfStream);
end;
result := intBitsToFloat((b3 shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff));
end;
function DataInputStream.readDoubleLE(): double;
var
b0: long;
b1: long;
b2: long;
b3: long;
b4: long;
b5: long;
b6: long;
b7: long;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
b2 := stream.read();
b3 := stream.read();
b4 := stream.read();
b5 := stream.read();
b6 := stream.read();
b7 := stream.read();
if (b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7) < 0 then begin
raise EOFException.create('DataInputStream.readDoubleLE: ' + msgEndOfStream);
end;
result := longBitsToDouble((b7 shl 56) or ((b6 and $ff) shl 48) or ((b5 and $ff) shl 40) or ((b4 and $ff) shl 32) or ((b3 and $ff) shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff));
end;
function DataInputStream.readRealLE(): real;
var
a0: int;
a1: int;
b0: long;
b1: long;
b2: long;
b3: long;
b4: long;
b5: long;
b6: long;
b7: long;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
b2 := stream.read();
b3 := stream.read();
b4 := stream.read();
b5 := stream.read();
b6 := stream.read();
b7 := stream.read();
a0 := stream.read();
a1 := stream.read();
if (b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7 or long(a0) or long(a1)) < 0 then begin
raise EOFException.create('DataInputStream.readRealLE: ' + msgEndOfStream);
end;
a0 := (a1 shl 8) or (a0 and $ff);
b0 := (b7 shl 56) or ((b6 and $ff) shl 48) or ((b5 and $ff) shl 40) or ((b4 and $ff) shl 32) or ((b3 and $ff) shl 24) or ((b2 and $ff) shl 16) or ((b1 and $ff) shl 8) or (b0 and $ff);
result := realBuild(a0, b0);
end;
function DataInputStream.readUnsignedShortLE(): int;
var
b0: int;
b1: int;
stream: Input;
begin
stream := self.stream;
b0 := stream.read();
b1 := stream.read();
if (b0 or b1) < 0 then begin
raise EOFException.create('DataInputStream.readUnsignedShortLE: ' + msgEndOfStream);
end;
result := ((b1 and $ff) shl 8) or (b0 and $ff);
end;
function DataInputStream.readUTF(): UnicodeString;
var
i: int;
slen: int;
rlen: int;
char1: int;
char2: int;
char3: int;
str: byte_Array1d;
buf: short_Array1d;
begin
slen := readUnsignedShort();
if slen <= 0 then begin
result := '';
exit;
end;
str := byte_Array1d_create(slen);
readFully(str, 0, slen);
rlen := 0;
buf := short_Array1d_create(slen);
i := 0;
while i < slen do begin
char1 := str[i] and $ff;
inc(i);
if (char1 >= $00) and (char1 < $80) then begin
buf[rlen] := short(char1);
inc(rlen);
end else
if (char1 >= $c0) and (char1 < $e0) then begin
char2 := 0;
if i < slen then begin
char2 := str[i] and $ff;
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := short(((char1 and $1f) shl 6) or (char2 and $3f));
inc(rlen);
end else
if (char1 >= $e0) and (char1 < $f0) then begin
char2 := 0;
char3 := 0;
if i < slen then begin
char2 := str[i] and $ff;
if (char2 and $c0) <> $80 then begin
char2 := 0;
end else begin
inc(i);
end;
end;
if i < slen then begin
char3 := str[i] and $ff;
if (char3 and $c0) <> $80 then begin
char3 := 0;
end else begin
inc(i);
end;
end;
buf[rlen] := short(((char1 and $0f) shl 12) or ((char2 and $3f) shl 6) or (char3 and $3f));
inc(rlen);
end;
end;
result := UnicodeString_create(buf, 0, rlen);
end;
procedure DataInputStream.readFully(const dst: byte_Array1d);
var
offset: int;
length: int;
readed: int;
stream: Input;
begin
offset := 0;
length := system.length(dst);
stream := self.stream;
while length > 0 do begin
readed := stream.read(dst, offset, length);
if readed <= 0 then begin
raise EOFException.create('DataInputStream.readFully: ' + msgEndOfStream);
end;
inc(offset, readed);
dec(length, readed);
end;
end;
procedure DataInputStream.readFully(const dst: byte_Array1d; offset, length: int);
var
readed: int;
stream: Input;
begin
arrayCheckBounds('DataInputStream.readFully', system.length(dst), offset, length);
stream := self.stream;
while length > 0 do begin
readed := stream.read(dst, offset, length);
if readed <= 0 then begin
raise EOFException.create('DataInputStream.readFully: ' + msgEndOfStream);
end;
inc(offset, readed);
dec(length, readed);
end;
end;
procedure DataInputStream.close();
begin
stream.close();
end;
{%endregion}
{%region DataOutputStream }
constructor DataOutputStream.create(stream: Output);
begin
inherited create();
self.stream := stream;
end;
procedure DataOutputStream.flush();
begin
stream.flush();
end;
procedure DataOutputStream.write(data: int);
begin
stream.write(data);
end;
procedure DataOutputStream.write(const src: byte_Array1d);
begin
stream.write(src);
end;
procedure DataOutputStream.write(const src: byte_Array1d; offset, length: int);
begin
stream.write(src, offset, length);
end;
procedure DataOutputStream.writeBoolean(data: boolean);
begin
if data then begin
stream.write(1);
end else begin
stream.write(0);
end;
end;
procedure DataOutputStream.writeChar(data: char);
begin
stream.write(int(data));
end;
procedure DataOutputStream.writeWChar(data: wchar);
var
stream: Output;
begin
stream := self.stream;
stream.write(int(data) shr 8);
stream.write(int(data));
end;
procedure DataOutputStream.writeByte(data: int);
begin
stream.write(data);
end;
procedure DataOutputStream.writeShort(data: int);
var
stream: Output;
begin
stream := self.stream;
stream.write(data shr 8);
stream.write(data);
end;
procedure DataOutputStream.writeInt(data: int);
var
stream: Output;
begin
stream := self.stream;
stream.write(data shr $18);
stream.write(data shr $10);
stream.write(data shr $08);
stream.write(data);
end;
procedure DataOutputStream.writeLong(data: long);
var
stream: Output;
begin
stream := self.stream;
stream.write(int(data shr $38));
stream.write(int(data shr $30));
stream.write(int(data shr $28));
stream.write(int(data shr $20));
stream.write(int(data shr $18));
stream.write(int(data shr $10));
stream.write(int(data shr $08));
stream.write(int(data));
end;
procedure DataOutputStream.writeFloat(data: float);
begin
writeInt(floatToIntBits(data));
end;
procedure DataOutputStream.writeDouble(data: double);
begin
writeLong(doubleToLongBits(data));
end;
procedure DataOutputStream.writeReal(const data: real);
begin
writeShort(realExponent(data));
writeLong(realSignificand(data));
end;
procedure DataOutputStream.writeWCharLE(data: wchar);
var
stream: Output;
begin
stream := self.stream;
stream.write(int(data));
stream.write(int(data) shr 8);
end;
procedure DataOutputStream.writeShortLE(data: int);
var
stream: Output;
begin
stream := self.stream;
stream.write(data);
stream.write(data shr 8);
end;
procedure DataOutputStream.writeIntLE(data: int);
var
stream: Output;
begin
stream := self.stream;
stream.write(data);
stream.write(data shr $08);
stream.write(data shr $10);
stream.write(data shr $18);
end;
procedure DataOutputStream.writeLongLE(data: long);
var
stream: Output;
begin
stream := self.stream;
stream.write(int(data));
stream.write(int(data shr $08));
stream.write(int(data shr $10));
stream.write(int(data shr $18));
stream.write(int(data shr $20));
stream.write(int(data shr $28));
stream.write(int(data shr $30));
stream.write(int(data shr $38));
end;
procedure DataOutputStream.writeFloatLE(data: float);
begin
writeIntLE(floatToIntBits(data));
end;
procedure DataOutputStream.writeDoubleLE(data: double);
begin
writeLongLE(doubleToLongBits(data));
end;
procedure DataOutputStream.writeRealLE(const data: real);
begin
writeLongLE(realSignificand(data));
writeShortLE(realExponent(data));
end;
procedure DataOutputStream.writeUTF(const data: UnicodeString);
var
i: int;
slen: int;
rlen: int;
code: int;
buf: byte_Array1d;
begin
slen := length(data);
if (slen > $ffff) or (slen < 0) then begin
raise UTFDataFormatException.create('DataOutputStream.writeUTF: ' + msgUTFDataTooLong);
end;
rlen := 0;
for i := slen downto 1 do begin
code := int(data[i]);
if (code >= $0001) and (code < $0080) then begin
inc(rlen, 1);
end else
if code < $0800 then begin
inc(rlen, 2);
end else begin
inc(rlen, 3);
end;
end;
if rlen > $ffff then begin
raise UTFDataFormatException.create('DataOutputStream.writeUTF: ' + msgUTFDataTooLong);
end;
buf := byte_Array1d_create(rlen);
rlen := 0;
for i := 0 to slen - 1 do begin
code := int(data[i + 1]);
if (code >= $0001) and (code < $0080) then begin
buf[rlen] := byte(code);
inc(rlen);
end else
if code < $0800 then begin
buf[rlen] := byte($c0 + (code shr 6));
buf[rlen + 1] := byte($80 + (code and $3f));
inc(rlen, 2);
end else begin
buf[rlen] := byte($e0 + (code shr 12));
buf[rlen + 1] := byte($80 + ((code shr 6) and $3f));
buf[rlen + 2] := byte($80 + (code and $3f));
inc(rlen, 3);
end;
end;
writeShort(rlen);
write(buf, 0, rlen);
end;
procedure DataOutputStream.writeAnsiChars(const data: AnsiString);
var
i: int;
stream: Output;
begin
stream := self.stream;
for i := 0 to length(data) - 1 do begin
stream.write(int(data[i + 1]));
end;
end;
procedure DataOutputStream.writeUnicodeChars(const data: UnicodeString);
var
i: int;
c: int;
stream: Output;
begin
stream := self.stream;
for i := 0 to length(data) - 1 do begin
c := int(data[i + 1]);
stream.write(c shr 8);
stream.write(c);
end;
end;
procedure DataOutputStream.writeUnicodeCharsLE(const data: UnicodeString);
var
i: int;
c: int;
stream: Output;
begin
stream := self.stream;
for i := 0 to length(data) - 1 do begin
c := int(data[i + 1]);
stream.write(c);
stream.write(c shr 8);
end;
end;
procedure DataOutputStream.close();
begin
stream.close();
end;
{%endregion}
{%region ByteArrayInputStream }
constructor ByteArrayInputStream.create(const buffer: byte_Array1d; offset: int);
begin
inherited create();
self.offset := offset;
self.buffer := buffer;
end;
function ByteArrayInputStream.seekSupported(): boolean;
begin
result := true;
end;
function ByteArrayInputStream.seek(delta: long): long;
var
cap: int;
pos: int;
newpos: int;
begin
cap := length(buffer);
pos := intBound(0, offset, cap);
newpos := int(longBound(0, long(pos) + delta, long(cap)));
self.offset := newpos;
result := newpos;
end;
function ByteArrayInputStream.reset(position: long): long;
var
cap: int;
newpos: int;
begin
cap := length(buffer);
newpos := int(longBound(0, position, long(cap)));
self.offset := newpos;
result := newpos;
end;
function ByteArrayInputStream.position(): long;
begin
result := intBound(0, offset, length(buffer));
end;
function ByteArrayInputStream.available(): long;
var
cap: int;
begin
cap := length(buffer);
result := cap - intBound(0, offset, cap);
end;
function ByteArrayInputStream.size(): long;
begin
result := length(buffer);
end;
function ByteArrayInputStream.read(): int;
var
buf: byte_Array1d;
pos: int;
begin
buf := self.buffer;
pos := self.offset;
if pos < 0 then pos := 0;
if pos >= system.length(buf) then begin
result := -1;
exit;
end;
self.offset := pos + 1;
result := buf[pos] and $ff;
end;
function ByteArrayInputStream.read(const dst: byte_Array1d; offset, length: int): int;
var
buf: byte_Array1d;
pos: int;
cap: int;
ready: int;
begin
arrayCheckBounds('ByteArrayInputStream.read', system.length(dst), offset, length);
if length <= 0 then begin
result := 0;
exit;
end;
buf := self.buffer;
pos := self.offset;
cap := system.length(buf);
if pos < 0 then pos := 0;
if pos >= cap then begin
result := -1;
exit;
end;
ready := intMin(cap - pos, length);
self.offset := pos + ready;
arraycopyPrimitives(buf, pos, dst, offset, ready);
result := ready;
end;
{%endregion}
{%region ByteArrayOutputStream }
constructor ByteArrayOutputStream.create(initialCapacity: int);
begin
inherited create();
self.buffer := byte_Array1d_create(intMax(initialCapacity, $1f));
end;
function ByteArrayOutputStream.toString(): AnsiString;
var
buf: byte_Array1d;
begin
buf := buffer;
result := AnsiString_create(buf, 0, intBound(0, offset, length(buf)));
end;
function ByteArrayOutputStream.toByteArray(): byte_Array1d;
var
buf: byte_Array1d;
pos: int;
begin
buf := buffer;
pos := intBound(0, offset, length(buf));
result := byte_Array1d_create(pos);
arraycopyPrimitives(buf, 0, result, 0, pos);
end;
function ByteArrayOutputStream.size(): int;
begin
result := intBound(0, offset, length(buffer));
end;
procedure ByteArrayOutputStream.reset();
begin
offset := 0;
end;
procedure ByteArrayOutputStream.write(data: int);
var
buf: byte_Array1d;
cap: int;
pos: int;
newbuf: byte_Array1d;
newcap: int;
begin
buf := self.buffer;
cap := system.length(buf);
pos := intBound(0, self.offset, cap);
if pos = INT_MAX_VALUE then begin
raise IOException.create('ByteArrayOutputStream.write: ' + msgArrayFull);
end;
if pos = cap then begin
newcap := int(longMin((long(cap) shl 1) + 1, INT_MAX_VALUE));
newbuf := byte_Array1d_create(newcap);
arraycopyPrimitives(buf, 0, newbuf, 0, pos);
self.buffer := newbuf;
buf := newbuf;
end;
self.offset := pos + 1;
buf[pos] := byte(data);
end;
procedure ByteArrayOutputStream.write(const src: byte_Array1d; offset, length: int);
var
buf: byte_Array1d;
cap: int;
pos: int;
newbuf: byte_Array1d;
newcap: int;
newpos: int;
begin
arrayCheckBounds('ByteArrayOutputStream.write', system.length(src), offset, length);
if length <= 0 then exit;
buf := self.buffer;
cap := system.length(buf);
pos := intBound(0, self.offset, cap);
newpos := pos + length;
if newpos < 0 then begin
raise IOException.create('ByteArrayOutputStream.write: ' + msgArrayFull);
end;
if newpos > cap then begin
newcap := int(longMin((long(cap) shl 1) + 1, INT_MAX_VALUE));
if newcap < newpos then newcap := int(longMin(long(newpos) + $1f, INT_MAX_VALUE));
newbuf := byte_Array1d_create(newcap);
arraycopyPrimitives(buf, 0, newbuf, 0, pos);
self.buffer := newbuf;
buf := newbuf;
end;
self.offset := newpos;
arraycopyPrimitives(src, offset, buf, pos, length);
end;
{%endregion}
{%region ByteArrayIOStream }
constructor ByteArrayIOStream.create(initialCapacity: int);
var
inputPtr: InputStream;
outputPtr: OutputStream;
begin
inherited create();
inputPtr := ByteArrayIOStream0InputStream.create(self);
outputPtr := ByteArrayIOStream0OutputStream.create(self);
if initialCapacity < $1f then initialCapacity := $1f;
self.inputPtr := inputPtr;
self.inputIntf := inputPtr;
self.outputPtr := outputPtr;
self.outputIntf := outputPtr;
self.buffer := byte_Array1d_create(initialCapacity);
end;
constructor ByteArrayIOStream.create(const buffer: byte_Array1d; writePosition, readPosition: int);
var
len: int;
cap: int;
newbuf: byte_Array1d;
inputPtr: InputStream;
outputPtr: OutputStream;
begin
inherited create();
len := length(buffer);
cap := int(longMin(long(len) + $1f, INT_MAX_VALUE));
newbuf := byte_Array1d_create(cap);
arraycopyPrimitives(buffer, 0, newbuf, 0, len);
inputPtr := ByteArrayIOStream0InputStream.create(self);
outputPtr := ByteArrayIOStream0OutputStream.create(self);
if writePosition < 0 then writePosition := 0;
if writePosition > len then writePosition := len;
if readPosition < 0 then readPosition := 0;
if readPosition > len then readPosition := len;
self.inputPos := readPosition;
self.inputPtr := inputPtr;
self.inputIntf := inputPtr;
self.outputPos := writePosition;
self.outputPtr := outputPtr;
self.outputIntf := outputIntf;
self.bufferSize := len;
self.buffer := newbuf;
end;
function ByteArrayIOStream.toString(): AnsiString;
begin
result := AnsiString_create(buffer, 0, bufferSize);
end;
function ByteArrayIOStream.toByteArray(): byte_Array1d;
var
len: int;
begin
len := bufferSize;
result := byte_Array1d_create(len);
arraycopyPrimitives(buffer, 0, result, 0, len);
end;
function ByteArrayIOStream.size(): int;
begin
result := bufferSize;
end;
function ByteArrayIOStream.seekSupported(): boolean;
begin
result := true;
end;
function ByteArrayIOStream.truncateSupported(): boolean;
begin
result := true;
end;
function ByteArrayIOStream.seek(delta: long): long;
var
newpos: int;
begin
newpos := int(longBound(0, outputPos + delta, bufferSize));
outputPos := newpos;
result := newpos;
end;
function ByteArrayIOStream.reset(position: long): long;
var
newpos: int;
begin
newpos := int(longBound(0, position, bufferSize));
outputPos := newpos;
result := newpos;
end;
function ByteArrayIOStream.position(): long;
begin
result := outputPos;
end;
function ByteArrayIOStream.truncate(): long;
var
truncPos: int;
begin
truncPos := outputPos;
if inputPos > truncPos then inputPos := truncPos;
bufferSize := truncPos;
result := truncPos;
end;
function ByteArrayIOStream.getInputStream(): InputStream;
begin
result := inputPtr;
end;
function ByteArrayIOStream.getOutputStream(): OutputStream;
begin
result := outputPtr;
end;
procedure ByteArrayIOStream.close();
begin
ByteArrayIOStream0InputStream(inputPtr).owner := nil;
ByteArrayIOStream0OutputStream(outputPtr).owner := nil;
inherited close();
end;
{%endregion}
{%region ByteArrayIOStream0InputStream }
constructor ByteArrayIOStream0InputStream.create(owner: ByteArrayIOStream);
begin
inherited create();
self.owner := owner;
end;
function ByteArrayIOStream0InputStream.seekSupported(): boolean;
begin
result := true;
end;
function ByteArrayIOStream0InputStream.seek(delta: long): long;
var
newpos: int;
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.seek: ' + msgParentIOStreamClosed);
end;
newpos := int(longBound(0, long(owner.inputPos) + delta, long(owner.bufferSize)));
owner.inputPos := newpos;
result := newpos;
end;
function ByteArrayIOStream0InputStream.reset(position: long): long;
var
newpos: int;
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.reset: ' + msgParentIOStreamClosed);
end;
newpos := int(longBound(0, position, long(owner.bufferSize)));
owner.inputPos := newpos;
result := newpos;
end;
function ByteArrayIOStream0InputStream.position(): long;
var
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.position: ' + msgParentIOStreamClosed);
end;
result := owner.inputPos;
end;
function ByteArrayIOStream0InputStream.available(): long;
var
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.available: ' + msgParentIOStreamClosed);
end;
result := owner.bufferSize - owner.inputPos;
end;
function ByteArrayIOStream0InputStream.size(): long;
var
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.size: ' + msgParentIOStreamClosed);
end;
result := owner.bufferSize;
end;
function ByteArrayIOStream0InputStream.read(): int;
var
pos: int;
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.read: ' + msgParentIOStreamClosed);
end;
pos := owner.inputPos;
if pos >= owner.bufferSize then begin
result := -1;
exit;
end;
owner.inputPos := pos + 1;
result := owner.buffer[pos] and $ff;
end;
function ByteArrayIOStream0InputStream.read(const dst: byte_Array1d; offset, length: int): int;
var
pos: int;
ready: int;
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('InputStream.read: ' + msgParentIOStreamClosed);
end;
arrayCheckBounds('InputStream.read', system.length(dst), offset, length);
if length <= 0 then begin
result := 0;
exit;
end;
pos := owner.inputPos;
ready := intMin(owner.bufferSize - pos, length);
arraycopyPrimitives(owner.buffer, pos, dst, offset, ready);
owner.inputPos := pos + ready;
result := ready;
end;
{%endregion}
{%region ByteArrayIOStream0OutputStream }
constructor ByteArrayIOStream0OutputStream.create(owner: ByteArrayIOStream);
begin
inherited create();
self.owner := owner;
end;
procedure ByteArrayIOStream0OutputStream.write(data: int);
var
buf: byte_Array1d;
pos: int;
len: int;
cap: int;
newbuf: byte_Array1d;
newpos: int;
newcap: int;
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('OutputStream.write: ' + msgParentIOStreamClosed);
end;
buf := owner.buffer;
pos := owner.outputPos;
len := owner.bufferSize;
cap := system.length(buf);
newpos := pos + 1;
if newpos < 0 then begin
raise IOException.create('OutputStream.write: ' + msgArrayFull);
end;
if newpos > cap then begin
newcap := int(longMin((long(cap) shl 1) + 1, INT_MAX_VALUE));
newbuf := byte_Array1d_create(newcap);
arraycopyPrimitives(buf, 0, newbuf, 0, len);
owner.buffer := newbuf;
buf := newbuf;
end;
buf[pos] := byte(data);
owner.outputPos := newpos;
if len < newpos then owner.bufferSize := newpos;
end;
procedure ByteArrayIOStream0OutputStream.write(const src: byte_Array1d; offset, length: int);
var
buf: byte_Array1d;
pos: int;
len: int;
cap: int;
newbuf: byte_Array1d;
newpos: int;
newcap: int;
owner: ByteArrayIOStream;
begin
owner := self.owner;
if owner = nil then begin
raise IOException.create('OutputStream.write: ' + msgParentIOStreamClosed);
end;
arrayCheckBounds('OutputStream.write', system.length(src), offset, length);
if length <= 0 then exit;
buf := owner.buffer;
pos := owner.outputPos;
len := owner.bufferSize;
cap := system.length(buf);
newpos := pos + length;
if newpos < 0 then begin
raise IOException.create('OutputStream.write: ' + msgArrayFull);
end;
if newpos > cap then begin
newcap := int(longMin((long(cap) shl 1) + 1, INT_MAX_VALUE));
if newcap < newpos then newcap := int(longMin(long(newpos) + $1f, INT_MAX_VALUE));
newbuf := byte_Array1d_create(newcap);
arraycopyPrimitives(buf, 0, newbuf, 0, len);
owner.buffer := newbuf;
buf := newbuf;
end;
arraycopyPrimitives(src, offset, buf, pos, length);
owner.outputPos := newpos;
if len < newpos then owner.bufferSize := newpos;
end;
{%endregion}
initialization
classInfoAdd([
typeInfo(Closeable),
typeInfo(Input),
typeInfo(DataInput),
typeInfo(Output),
typeInfo(DataOutput)
]);
end.