{
pascalx.io.bytearray — классы ввода-вывода, использующие массивы байтов
в оперативной памяти.
Copyright © 2021, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или изменять
её на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
}
unit pascalx.io.bytearray;
{$MODE DELPHI}
interface
{%region} uses
pascalx.lang,
pascalx.io,
pascalx.io.extension;
{%endregion}
{$TYPEINFO ON}
{$CALLING REGISTER}
const UNIT_NAME = 'pascalx.io.bytearray';
{%region} type
ByteArrayInputStream = class;
ByteArrayOutputStream = class;
ByteArrayBidirectStream = class;
ByteArrayBidirectStreamReader = class;
ByteArrayBidirectStreamWriter = class;
ByteArrayInputStream = class(&Object, Extension, MarkExtension, ByteReader, SeekExtension, LimitedSizeExtension, Extendable)
protected
fldMarked: int;
fldLength: int;
fldPosition: int;
fldArray: byte_Array1d;
public
constructor create(); overload;
constructor create(const aarray: byte_Array1d); overload;
constructor create(const aarray: byte_Array1d; length: int); overload;
constructor create(const aarray: byte_Array1d; length, position: int); overload;
procedure reset(); virtual;
procedure mark(transferLimit: int); virtual;
procedure close(); virtual;
function read(): int; virtual; overload;
function read(const dst: byte_Array1d): int; virtual; overload;
function read(const dst: byte_Array1d; offset, length: int): int; virtual; overload;
function skip(bytesQuantity: long): long; virtual;
function seek(offset: long; from: SeekFrom): long; virtual;
function position(): long; virtual;
function size(): long; virtual;
function available(): long; virtual;
function getExtensions(): Extension_Array1d; virtual;
function getExtension(const typ: ShortString): Extension; virtual;
end;
ByteArrayOutputStream = class(&Object, Extension, MarkExtension, ByteWriter, TruncateExtension, SeekExtension, LimitedSizeExtension, Extendable)
protected
fldMarked: int;
fldLength: int;
fldPosition: int;
fldArray: byte_Array1d;
function madeLarger(curLength, newLength: int): byte_Array1d; virtual;
public
constructor create(); overload;
constructor create(const aarray: byte_Array1d); overload;
constructor create(const aarray: byte_Array1d; length: int); overload;
constructor create(const aarray: byte_Array1d; length, position: int); overload;
procedure reset(); virtual;
procedure mark(transferLimit: int); virtual;
procedure close(); virtual;
procedure write(byteData: int); virtual; overload;
procedure write(const src: byte_Array1d); virtual; overload;
procedure write(const src: byte_Array1d; offset, length: int); virtual; overload;
procedure flush(); virtual;
procedure truncate(); virtual;
function toString(): AnsiString; override;
function seek(offset: long; from: SeekFrom): long; virtual;
function position(): long; virtual;
function size(): long; virtual;
function available(): long; virtual;
function getExtensions(): Extension_Array1d; virtual;
function getExtension(const typ: ShortString): Extension; virtual;
function toByteArray(): byte_Array1d; virtual;
end;
ByteArrayBidirectStream = class(&Object, ByteStream, Extendable)
private
procedure setByte(index: int; value: byte);
function getByte(index: int): byte;
function getLength(): int;
function getArray(): byte_Array1d;
function getByteArrayReader(): ByteArrayInputStream;
function getByteArrayWriter(): ByteArrayOutputStream;
protected
fldReader: ByteArrayBidirectStreamReader;
fldWriter: ByteArrayBidirectStreamWriter;
procedure setReadPosition(newReadPosition: int); virtual;
procedure setWritePosition(newWritePosition: int); virtual;
function getReadPosition(): int; virtual;
function getWritePosition(): int; virtual;
function createReader(const aarray: byte_Array1d; length, position: int): ByteArrayBidirectStreamReader; virtual;
function createWriter(const aarray: byte_Array1d; length, position: int): ByteArrayBidirectStreamWriter; virtual;
public
constructor create(); overload;
constructor create(const aarray: byte_Array1d); overload;
constructor create(const aarray: byte_Array1d; length: int); overload;
constructor create(const aarray: byte_Array1d; length, readPosition, writePosition: int); overload;
destructor destroy; override;
procedure close(); virtual;
procedure setData(const aarray: byte_Array1d; length: int); virtual;
function getExtensions(): Extension_Array1d; virtual;
function getExtension(const typ: ShortString): Extension; virtual;
function getReader(): ByteReader;
function getWriter(): ByteWriter;
property length: int read getLength;
property byteArray: byte_Array1d read getArray;
property bytes[index: int]: byte read getByte write setByte; default;
published
property reader: ByteReader read getReader;
property writer: ByteWriter read getWriter;
property readPosition: int read getReadPosition write setReadPosition;
property writePosition: int read getWritePosition write setWritePosition;
property byteArrayReader: ByteArrayInputStream read getByteArrayReader;
property byteArrayWriter: ByteArrayOutputStream read getByteArrayWriter;
end;
ByteArrayBidirectStreamReader = class(ByteArrayInputStream)
private
fldCanDestroy: boolean;
protected
procedure setData(const newArray: byte_Array1d; newLength: int); virtual;
procedure setPosition(newPosition: int); virtual;
procedure notifyLengthChanged(newLength: int); virtual;
public
constructor create(const aarray: byte_Array1d; length, position: int);
procedure beforeDestruction(); override;
procedure close(); override; final;
end;
ByteArrayBidirectStreamWriter = class(ByteArrayOutputStream)
private
fldCanDestroy: boolean;
protected
fldSource: ByteArrayBidirectStreamReader;
procedure setData(const newArray: byte_Array1d; newLength: int); virtual;
procedure setPosition(newPosition: int); virtual;
procedure notifyLengthChanged(newLength: int); virtual;
function madeLarger(curLength, newLength: int): byte_Array1d; override;
public
constructor create(const aarray: byte_Array1d; length, position: int);
procedure beforeDestruction(); override;
procedure close(); override; final;
procedure truncate(); override;
end;
{%endregion}
implementation
{$CALLING REGISTER}
{%region ByteArrayInputStream }
constructor ByteArrayInputStream.create();
begin
inherited create();
end;
constructor ByteArrayInputStream.create(const aarray: byte_Array1d);
begin
inherited create();
fldLength := length(aarray);
fldArray := aarray;
end;
constructor ByteArrayInputStream.create(const aarray: byte_Array1d; length: int);
var
alength: int;
begin
inherited create();
if length > 0 then begin
alength := system.length(aarray);
if length < alength then begin
fldLength := length;
end else begin
fldLength := alength;
end;
fldArray := aarray;
end;
end;
constructor ByteArrayInputStream.create(const aarray: byte_Array1d; length, position: int);
var
alength: int;
slength: int;
begin
inherited create();
if length > 0 then begin
alength := system.length(aarray);
if length < alength then begin
slength := length;
end else begin
slength := alength;
end;
fldLength := slength;
if position < 0 then begin
fldPosition := 0;
end else
if position < slength then begin
fldPosition := position;
end else begin
fldPosition := slength;
end;
fldArray := aarray;
end;
end;
procedure ByteArrayInputStream.reset();
begin
fldPosition := fldMarked;
end;
procedure ByteArrayInputStream.mark(transferLimit: int);
begin
fldMarked := fldPosition;
end;
procedure ByteArrayInputStream.close();
begin
destroy;
end;
function ByteArrayInputStream.read(): int;
var
position: int;
begin
position := fldPosition;
if position >= fldLength then begin
result := -1;
exit;
end;
fldPosition := position + 1;
result := fldArray[position] and $ff;
end;
function ByteArrayInputStream.read(const dst: byte_Array1d): int;
begin
result := read(dst, 0, length(dst));
end;
function ByteArrayInputStream.read(const dst: byte_Array1d; offset, length: int): int;
var
position: int;
remainder: int;
begin
&Array.checkBounds(dst, offset, length);
if length <= 0 then begin
result := 0;
exit;
end;
position := fldPosition;
remainder := fldLength - position;
if remainder <= 0 then begin
result := -1;
exit;
end;
if length > remainder then length := remainder;
&Array.copyPrimitives(fldArray, position, dst, offset, length);
fldPosition := position + length;
result := length;
end;
function ByteArrayInputStream.skip(bytesQuantity: long): long;
var
length: int;
position: int;
remainder: int;
begin
if bytesQuantity <= 0 then begin
result := 0;
exit;
end;
if bytesQuantity < CoInt.MAX_VALUE then begin
length := int(bytesQuantity);
end else begin
length := CoInt.MAX_VALUE;
end;
position := fldPosition;
remainder := fldLength - position;
if length > remainder then length := remainder;
fldPosition := position + length;
result := length;
end;
function ByteArrayInputStream.seek(offset: long; from: SeekFrom): long;
var
length: long;
position: long;
begin
length := fldLength;
case from of
SeekFrom.sfBegin:
position := offset;
SeekFrom.sfEnd:
position := offset + length;
SeekFrom.sfCurrent:
position := offset + fldPosition;
else
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('from') ]));
end;
if position < 0 then position := 0;
if position > length then position := length;
fldPosition := int(position);
result := position;
end;
function ByteArrayInputStream.position(): long;
begin
result := fldPosition;
end;
function ByteArrayInputStream.size(): long;
begin
result := fldLength;
end;
function ByteArrayInputStream.available(): long;
begin
result := fldLength - fldPosition;
end;
function ByteArrayInputStream.getExtensions(): Extension_Array1d;
begin
result := [ self as Extension ];
end;
function ByteArrayInputStream.getExtension(const typ: ShortString): Extension;
var
ext: Extension;
begin
ext := self;
if Lang.isInstance(ext, typ) then begin
result := Extension(Lang.cast(ext, typ));
exit;
end;
result := nil;
end;
{%endregion}
{%region ByteArrayOutputStream }
function ByteArrayOutputStream.madeLarger(curLength, newLength: int): byte_Array1d;
var
curCapacity: int;
newCapacity: int;
curArray: byte_Array1d;
newArray: byte_Array1d;
begin
if newLength < 0 then begin
raise BufferTooLargeError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.buffer-too-large'));
end;
newArray := fldArray;
curArray := newArray;
curCapacity := length(curArray);
if curCapacity <= 0 then begin
if newLength >= CoInt.MAX_VALUE - $7f then begin
newCapacity := CoInt.MAX_VALUE;
end else begin
newCapacity := newLength + $7f;
end;
newArray := &Array.newByte1d(newCapacity);
fldArray := newArray;
end else
if newLength > curCapacity then begin
newCapacity := (curCapacity shl 1) or 1;
if newCapacity < 0 then newCapacity := CoInt.MAX_VALUE;
if newCapacity < newLength then begin
if newLength >= CoInt.MAX_VALUE - $7f then begin
newCapacity := CoInt.MAX_VALUE;
end else begin
newCapacity := newLength + $7f;
end;
end;
newArray := &Array.newByte1d(newCapacity);
&Array.copyPrimitives(curArray, 0, newArray, 0, curLength);
fldArray := newArray;
end;
fldLength := newLength;
result := newArray;
end;
constructor ByteArrayOutputStream.create();
begin
inherited create();
fldArray := &Array.newByte1d($7f);
end;
constructor ByteArrayOutputStream.create(const aarray: byte_Array1d);
var
slength: int;
capacity: int;
sarray: byte_Array1d;
begin
inherited create();
slength := length(aarray);
if slength >= CoInt.MAX_VALUE - $7f then begin
capacity := CoInt.MAX_VALUE;
end else begin
capacity := slength + $7f;
end;
sarray := &Array.newByte1d(capacity);
&Array.copyPrimitives(aarray, 0, sarray, 0, slength);
fldLength := slength;
fldPosition := slength;
fldArray := sarray;
end;
constructor ByteArrayOutputStream.create(const aarray: byte_Array1d; length: int);
var
alength: int;
slength: int;
capacity: int;
sarray: byte_Array1d;
begin
inherited create();
alength := system.length(aarray);
if length < 0 then begin
slength := 0;
end else
if length < alength then begin
slength := length;
end else begin
slength := alength;
end;
if slength >= CoInt.MAX_VALUE - $7f then begin
capacity := CoInt.MAX_VALUE;
end else begin
capacity := slength + $7f;
end;
sarray := &Array.newByte1d(capacity);
&Array.copyPrimitives(aarray, 0, sarray, 0, slength);
fldLength := slength;
fldPosition := slength;
fldArray := sarray;
end;
constructor ByteArrayOutputStream.create(const aarray: byte_Array1d; length, position: int);
var
alength: int;
slength: int;
capacity: int;
sarray: byte_Array1d;
begin
inherited create();
alength := system.length(aarray);
if length < 0 then begin
slength := 0;
end else
if length < alength then begin
slength := length;
end else begin
slength := alength;
end;
if slength >= CoInt.MAX_VALUE - $7f then begin
capacity := CoInt.MAX_VALUE;
end else begin
capacity := slength + $7f;
end;
sarray := &Array.newByte1d(capacity);
&Array.copyPrimitives(aarray, 0, sarray, 0, slength);
fldLength := slength;
if position < 0 then begin
fldPosition := 0;
end else
if position < slength then begin
fldPosition := position;
end else begin
fldPosition := slength;
end;
fldArray := sarray;
end;
procedure ByteArrayOutputStream.reset();
begin
fldPosition := fldMarked;
end;
procedure ByteArrayOutputStream.mark(transferLimit: int);
begin
fldMarked := fldPosition;
end;
procedure ByteArrayOutputStream.close();
begin
destroy;
end;
procedure ByteArrayOutputStream.write(byteData: int);
var
curLength: int;
curPosition: int;
newPosition: int;
locArray: byte_Array1d;
begin
curLength := fldLength;
curPosition := fldPosition;
newPosition := curPosition + 1;
if (newPosition >= 0) and (newPosition <= curLength) then begin
locArray := fldArray;
end else begin
locArray := madeLarger(curLength, newPosition);
end;
locArray[curPosition] := byte(byteData);
fldPosition := newPosition;
end;
procedure ByteArrayOutputStream.write(const src: byte_Array1d);
begin
write(src, 0, length(src));
end;
procedure ByteArrayOutputStream.write(const src: byte_Array1d; offset, length: int);
var
curLength: int;
curPosition: int;
newPosition: int;
locArray: byte_Array1d;
begin
&Array.checkBounds(src, offset, length);
if length > 0 then begin
curLength := fldLength;
curPosition := fldPosition;
newPosition := curPosition + length;
if (newPosition >= 0) and (newPosition <= curLength) then begin
locArray := fldArray;
end else begin
locArray := madeLarger(curLength, newPosition);
end;
&Array.copyPrimitives(src, offset, locArray, curPosition, length);
fldPosition := newPosition;
end;
end;
procedure ByteArrayOutputStream.flush();
begin
end;
procedure ByteArrayOutputStream.truncate();
var
newLength: int;
begin
newLength := fldPosition;
fldLength := newLength;
if fldMarked > newLength then fldMarked := newLength;
end;
function ByteArrayOutputStream.toString(): AnsiString;
begin
result := AnsiString.create(fldArray, 0, fldLength);
end;
function ByteArrayOutputStream.seek(offset: long; from: SeekFrom): long;
var
length: long;
position: long;
begin
length := fldLength;
case from of
SeekFrom.sfBegin:
position := offset;
SeekFrom.sfEnd:
position := offset + length;
SeekFrom.sfCurrent:
position := offset + fldPosition;
else
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument'), [ CoAnsiString.create('from') ]));
end;
if position < 0 then position := 0;
if position > length then position := length;
fldPosition := int(position);
result := position;
end;
function ByteArrayOutputStream.position(): long;
begin
result := fldPosition;
end;
function ByteArrayOutputStream.size(): long;
begin
result := fldLength;
end;
function ByteArrayOutputStream.available(): long;
begin
result := fldLength - fldPosition;
end;
function ByteArrayOutputStream.getExtensions(): Extension_Array1d;
begin
result := [ self as Extension ];
end;
function ByteArrayOutputStream.getExtension(const typ: ShortString): Extension;
var
ext: Extension;
begin
ext := self;
if Lang.isInstance(ext, typ) then begin
result := Extension(Lang.cast(ext, typ));
exit;
end;
result := nil;
end;
function ByteArrayOutputStream.toByteArray(): byte_Array1d;
var
locLength: int;
locArray: byte_Array1d;
begin
locLength := fldLength;
locArray := &Array.newByte1d(locLength);
&Array.copyPrimitives(fldArray, 0, locArray, 0, locLength);
result := locArray;
end;
{%endregion}
{%region ByteArrayBidirectStream }
procedure ByteArrayBidirectStream.setByte(index: int; value: byte);
var
writer: ByteArrayBidirectStreamWriter;
begin
writer := fldWriter;
if (index < 0) or (index >= writer.fldLength) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
writer.fldArray[index] := value;
end;
function ByteArrayBidirectStream.getByte(index: int): byte;
var
writer: ByteArrayBidirectStreamWriter;
begin
writer := fldWriter;
if (index < 0) or (index >= writer.fldLength) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
result := writer.fldArray[index];
end;
function ByteArrayBidirectStream.getLength(): int;
begin
result := fldWriter.fldLength;
end;
function ByteArrayBidirectStream.getArray(): byte_Array1d;
begin
result := fldWriter.fldArray;
end;
function ByteArrayBidirectStream.getByteArrayReader(): ByteArrayInputStream;
begin
result := fldReader;
end;
function ByteArrayBidirectStream.getByteArrayWriter(): ByteArrayOutputStream;
begin
result := fldWriter;
end;
procedure ByteArrayBidirectStream.setReadPosition(newReadPosition: int);
begin
fldReader.setPosition(newReadPosition);
end;
procedure ByteArrayBidirectStream.setWritePosition(newWritePosition: int);
begin
fldWriter.setPosition(newWritePosition);
end;
function ByteArrayBidirectStream.getReadPosition(): int;
begin
result := fldReader.fldPosition;
end;
function ByteArrayBidirectStream.getWritePosition(): int;
begin
result := fldWriter.fldPosition;
end;
function ByteArrayBidirectStream.createReader(const aarray: byte_Array1d; length, position: int): ByteArrayBidirectStreamReader;
begin
result := nil;
end;
function ByteArrayBidirectStream.createWriter(const aarray: byte_Array1d; length, position: int): ByteArrayBidirectStreamWriter;
begin
result := nil;
end;
constructor ByteArrayBidirectStream.create();
begin
create(nil, 0, 0, 0);
end;
constructor ByteArrayBidirectStream.create(const aarray: byte_Array1d);
begin
create(aarray, system.length(aarray), 0, 0);
end;
constructor ByteArrayBidirectStream.create(const aarray: byte_Array1d; length: int);
begin
create(aarray, length, 0, 0);
end;
constructor ByteArrayBidirectStream.create(const aarray: byte_Array1d; length, readPosition, writePosition: int);
var
barray: byte_Array1d;
reader: ByteArrayBidirectStreamReader;
writer: ByteArrayBidirectStreamWriter;
begin
inherited create();
writer := createWriter(aarray, length, writePosition);
if writer = nil then writer := ByteArrayBidirectStreamWriter.create(aarray, length, writePosition);
barray := writer.fldArray;
length := writer.fldLength;
reader := createReader(barray, length, readPosition);
if reader = nil then reader := ByteArrayBidirectStreamReader.create(barray, length, readPosition);
writer.fldSource := reader;
fldReader := reader;
fldWriter := writer;
end;
destructor ByteArrayBidirectStream.destroy;
var
writer: ByteArrayBidirectStreamWriter;
reader: ByteArrayBidirectStreamReader;
begin
writer := fldWriter;
reader := fldReader;
writer.fldCanDestroy := true;
reader.fldCanDestroy := true;
writer.free();
reader.free();
inherited destroy;
end;
procedure ByteArrayBidirectStream.close();
begin
destroy;
end;
procedure ByteArrayBidirectStream.setData(const aarray: byte_Array1d; length: int);
var
alength: int;
begin
alength := system.length(aarray);
if length < 0 then begin
length := 0;
end else
if length >= alength then begin
length := alength;
end;
fldReader.setData(aarray, length);
fldWriter.setData(aarray, length);
end;
function ByteArrayBidirectStream.getExtensions(): Extension_Array1d;
begin
result := nil;
end;
function ByteArrayBidirectStream.getExtension(const typ: ShortString): Extension;
begin
result := nil;
end;
function ByteArrayBidirectStream.getReader(): ByteReader;
begin
result := fldReader;
end;
function ByteArrayBidirectStream.getWriter(): ByteWriter;
begin
result := fldWriter;
end;
{%endregion}
{%region ByteArrayBidirectStreamReader }
procedure ByteArrayBidirectStreamReader.setData(const newArray: byte_Array1d; newLength: int);
begin
fldArray := newArray;
fldLength := newLength;
notifyLengthChanged(newLength);
end;
procedure ByteArrayBidirectStreamReader.setPosition(newPosition: int);
var
length: int;
begin
length := fldLength;
if newPosition < 0 then newPosition := 0;
if newPosition > length then newPosition := length;
fldPosition := newPosition;
end;
procedure ByteArrayBidirectStreamReader.notifyLengthChanged(newLength: int);
begin
if fldPosition > newLength then fldPosition := newLength;
if fldMarked > newLength then fldMarked := newLength;
end;
constructor ByteArrayBidirectStreamReader.create(const aarray: byte_Array1d; length, position: int);
begin
inherited create(aarray, length, position);
end;
procedure ByteArrayBidirectStreamReader.beforeDestruction();
begin
if not fldCanDestroy then begin
raise InvalidPointerError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.invalid-pointer'));
end;
end;
procedure ByteArrayBidirectStreamReader.close();
begin
end;
{%endregion}
{%region ByteArrayBidirectStreamWriter }
procedure ByteArrayBidirectStreamWriter.setData(const newArray: byte_Array1d; newLength: int);
begin
fldArray := newArray;
fldLength := newLength;
notifyLengthChanged(newLength);
end;
procedure ByteArrayBidirectStreamWriter.setPosition(newPosition: int);
var
length: int;
begin
length := fldLength;
if newPosition < 0 then newPosition := 0;
if newPosition > length then newPosition := length;
fldPosition := newPosition;
end;
procedure ByteArrayBidirectStreamWriter.notifyLengthChanged(newLength: int);
begin
if fldPosition > newLength then fldPosition := newLength;
if fldMarked > newLength then fldMarked := newLength;
end;
function ByteArrayBidirectStreamWriter.madeLarger(curLength, newLength: int): byte_Array1d;
var
newArray: byte_Array1d;
source: ByteArrayBidirectStreamReader;
begin
newArray := inherited madeLarger(curLength, newLength);
source := fldSource;
source.fldArray := newArray;
source.fldLength := newLength;
result := newArray;
end;
constructor ByteArrayBidirectStreamWriter.create(const aarray: byte_Array1d; length, position: int);
begin
inherited create(aarray, length, position);
end;
procedure ByteArrayBidirectStreamWriter.beforeDestruction();
begin
if not fldCanDestroy then begin
raise InvalidPointerError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.invalid-pointer'));
end;
end;
procedure ByteArrayBidirectStreamWriter.close();
begin
end;
procedure ByteArrayBidirectStreamWriter.truncate();
var
newLength: int;
begin
newLength := fldPosition;
fldLength := newLength;
self.notifyLengthChanged(newLength);
fldSource.notifyLengthChanged(newLength);
end;
{%endregion}
end.