Untitled

mail@pastecode.io avatar
unknown
pascal
6 months ago
2.6 kB
5
Indexable
Never
interface
 
  TMultiStream = class(TStream)
  public
    // потоки
    fStreams : TArray<TStream>;
    // лимит размера на поток, что бы был смысл записывать в несколько потоков при записи
    fSizePerStream : integer;
    function Read(var Buffer; Count: Longint): Longint; override;
    function Write(const Buffer; Count: Longint): Longint; override;
  end;
  TPartialStream = class(TStream)
  public
    //основой поток, так проще тестировать
    fBaseStream : TStream;
    //диапазон байт
    fOffsetMin, fOffsetMax : integer;
    function Read(var Buffer; Count: Longint): Longint; override;
    function Write(const Buffer; Count: Longint): Longint; override;
  end;
 
implementation
 
function TMultiStream.Read(var Buffer; Count: Longint): Longint;
begin
  //просто последовательное чтение потоков
  var aTotalReadCount : integer := 0;
  var aBufferPos := PByte(@Buffer);
  for var el in fStreams do begin
    var aReadCount := el.Read(aBufferPos^, Count);
    aBufferPos := aBufferPos + aReadCount;
    aTotalReadCount := aTotalReadCount + aReadCount;
    if aTotalReadCount >= Count then
      break;
    Count := Count - aReadCount;
  end;
  result := aTotalReadCount;
end;
 
function TMultiStream.Write(const Buffer; Count: Longint): Longint;
begin
  //запись в потоки учитывая лимит размера на поток
  var aTotalWriteCount : integer := 0;
  var aBufferPos := PByte(@Buffer);
  for var el in fStreams do begin
    if el.Position >= fSizePerStream then
      continue;
    var aWriteCount := el.Write(aBufferPos^, Min(Count, Count - el.Position));
    aBufferPos := aBufferPos + aWriteCount;
    aTotalWriteCount := aTotalWriteCount + aWriteCount;
    if aTotalWriteCount >= Count then
      break;
    Count := Count - aWriteCount;
  end;
  result := aTotalWriteCount;
end;
 
function TPartialStream.Read(var Buffer; Count: Longint): Longint;
begin
  if fBaseStream.Position < fOffsetMin then
    fBaseStream.Position := Min(fOffsetMin, fBaseStream.Size);
  var aMaxCount : longint := Min(Count, fOffsetMax - fBaseStream.Position);
  result := fBaseStream.Read(Buffer, aMaxCount);
end;
 
function TPartialStream.Write(const Buffer; Count: Longint): Longint;
begin
  if fBaseStream.Position < fOffsetMin then
    fBaseStream.Position := Min(fOffsetMin, fBaseStream.Size);
  var aMaxCount : longint := Min(Count, fOffsetMax - fBaseStream.Position);
  result := fBaseStream.Write(Buffer, aMaxCount);
end;