Sfoglia il codice sorgente

* implemented linked list for PagedDataFiFo

master
Bergmann89 9 anni fa
parent
commit
bc7faefe61
3 ha cambiato i file con 476 aggiunte e 186 eliminazioni
  1. +32
    -120
      Tests/UtilsTests.lps
  2. +300
    -6
      Tests/uGenericsTests.pas
  3. +144
    -60
      uutlGenerics.pas

+ 32
- 120
Tests/UtilsTests.lps Vedi File

@@ -10,34 +10,32 @@
<IsPartOfProject Value="True"/>
<EditorIndex Value="-1"/>
<CursorPos Y="22"/>
<UsageCount Value="24"/>
<UsageCount Value="30"/>
</Unit0>
<Unit1>
<Filename Value="uGenericsTests.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="uGenericsTests"/>
<TopLine Value="124"/>
<CursorPos X="27" Y="135"/>
<UsageCount Value="24"/>
<TopLine Value="1127"/>
<CursorPos X="73" Y="1148"/>
<UsageCount Value="30"/>
<Loaded Value="True"/>
</Unit1>
<Unit2>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\packages\fcl-fpcunit\src\fpcunit.pp"/>
<UnitName Value="fpcunit"/>
<EditorIndex Value="-1"/>
<TopLine Value="113"/>
<CursorPos X="21" Y="129"/>
<UsageCount Value="11"/>
</Unit2>
<Unit3>
<Filename Value="..\uutlGenerics.pas"/>
<UnitName Value="uutlGenerics"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="1"/>
<TopLine Value="448"/>
<CursorPos X="30" Y="461"/>
<UsageCount Value="12"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\uutlGenerics.pas"/>
<UnitName Value="uutlGenerics"/>
<EditorIndex Value="-1"/>
<TopLine Value="1952"/>
<CursorPos Y="1969"/>
<UsageCount Value="14"/>
</Unit3>
<Unit4>
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\2.7.1\source\rtl\inc\wstringh.inc"/>
@@ -50,7 +48,6 @@
<ComponentName Value="GUITestRunner"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="GuiTestRunner"/>
<EditorIndex Value="-1"/>
<TopLine Value="78"/>
<CursorPos X="3" Y="41"/>
@@ -62,137 +59,52 @@
<UsageCount Value="10"/>
</Unit6>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<JumpHistory Count="8" HistoryIndex="7">
<Position1>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1812" TopLine="1795"/>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="1145" TopLine="1122"/>
</Position1>
<Position2>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1813" TopLine="1795"/>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="1140" Column="19" TopLine="1122"/>
</Position2>
<Position3>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1826" TopLine="1798"/>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="1139" TopLine="1122"/>
</Position3>
<Position4>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1898" Column="4" TopLine="1884"/>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="1143" TopLine="1122"/>
</Position4>
<Position5>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="781" TopLine="768"/>
<Caret Line="1148" Column="59" TopLine="1122"/>
</Position5>
<Position6>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1954" TopLine="1937"/>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="1143" TopLine="1125"/>
</Position6>
<Position7>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1888" TopLine="1871"/>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="133" Column="15" TopLine="117"/>
</Position7>
<Position8>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1889" TopLine="1871"/>
</Position8>
<Position9>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1811" TopLine="1794"/>
</Position9>
<Position10>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1889" TopLine="1872"/>
</Position10>
<Position11>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1890" TopLine="1878"/>
</Position11>
<Position12>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1891" TopLine="1878"/>
</Position12>
<Position13>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1892" TopLine="1878"/>
</Position13>
<Position14>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1895" TopLine="1878"/>
</Position14>
<Position15>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1896" TopLine="1878"/>
</Position15>
<Position16>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1897" TopLine="1878"/>
</Position16>
<Position17>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1899" TopLine="1878"/>
</Position17>
<Position18>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1900" TopLine="1878"/>
</Position18>
<Position19>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1901" TopLine="1878"/>
</Position19>
<Position20>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1906" TopLine="1885"/>
</Position20>
<Position21>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1907" TopLine="1885"/>
</Position21>
<Position22>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1908" TopLine="1885"/>
</Position22>
<Position23>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1909" TopLine="1885"/>
</Position23>
<Position24>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1890" TopLine="1884"/>
</Position24>
<Position25>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="1888" TopLine="1882"/>
</Position25>
<Position26>
<Filename Value="..\uutlGenerics.pas"/>
<Caret Line="497" Column="53" TopLine="477"/>
</Position26>
<Position27>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="105" TopLine="88"/>
</Position27>
<Position28>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="123" Column="36" TopLine="112"/>
</Position28>
<Position29>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="827" Column="37" TopLine="813"/>
</Position29>
<Position30>
<Filename Value="uGenericsTests.pas"/>
<Caret Line="829" Column="44" TopLine="812"/>
</Position30>
<Caret Line="1146" Column="33" TopLine="1127"/>
</Position8>
</JumpHistory>
</ProjectSession>
<Debugging>
<Watches Count="2">
<Watches Count="3">
<Item1>
<Expression Value="aCount"/>
</Item1>
<Item2>
<Expression Value="aConsumer"/>
</Item2>
<Item3>
<Expression Value="PChar(@ReadPage^.Data[1023])"/>
</Item3>
</Watches>
</Debugging>
</CONFIG>

+ 300
- 6
Tests/uGenericsTests.pas Vedi File

@@ -1,6 +1,7 @@
unit uGenericsTests;

{$mode objfpc}{$H+}
{$modeswitch nestedprocvars}

interface

@@ -121,6 +122,15 @@ type
procedure WritePeekReadMultiPage;
procedure WriteDiscardReadSinglePage;
procedure WriteDiscardReadMultiPage;
procedure NestedProvider;
procedure NestedConsumer;
procedure StreamProvider;
procedure StreamConsumer;
procedure RandomSizeTest;
procedure BigDataBlocks;
procedure WriteSmallBlocks;
procedure ReadSmallBlocks;
procedure WriteHalfPageReadAll;
end;

implementation
@@ -748,7 +758,7 @@ begin
SetLength(buf2, l);
AssertEquals(l, fFiFo.Read(PByte(@buf2[1]), l));
AssertEquals(0, fFiFo.Size);
Assert(buf1 = buf2);
AssertEquals('Data', 0, CompareStr(buf1, buf2));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -765,7 +775,7 @@ begin
SetLength(buf2, l);
AssertEquals(l, fFiFo.Read(PByte(@buf2[1]), l));
AssertEquals(0, fFiFo.Size);
Assert(buf1 = buf2);
AssertEquals('Data', 0, CompareStr(buf1, buf2));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -787,7 +797,7 @@ begin
SetLength(buf3, l);
AssertEquals(l, fFiFo.Read(PByte(@buf3[1]), l));
AssertEquals(0, fFiFo.Size);
Assert(buf1 = buf3);
AssertEquals('Data', 0, CompareStr(buf1, buf3));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -809,7 +819,7 @@ begin
SetLength(buf3, l);
AssertEquals(l, fFiFo.Read(PByte(@buf3[1]), l));
AssertEquals(0, fFiFo.Size);
Assert(buf1 = buf3);
AssertEquals('Data', 0, CompareStr(buf1, buf3));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -831,7 +841,7 @@ begin
SetLength(buf2, l);
AssertEquals(l, fFiFo.Read(PByte(@buf2[1]), l));
AssertEquals(0, fFiFo.Size);
Assert(buf1 = buf2);
AssertEquals('Data', 0, CompareStr(buf1, buf2));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -853,7 +863,291 @@ begin
SetLength(buf2, l);
AssertEquals(l, fFiFo.Read(PByte(@buf2[1]), l));
AssertEquals(0, fFiFo.Size);
Assert(buf1 = buf2);
AssertEquals('Data', 0, CompareStr(buf1, buf2));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.NestedProvider;
var
pos: Integer;
len: Integer;
data: String;
tmp: String;

function GiveData(const aBuffer: PByte; aCount: Integer): Integer;
begin
result := aCount;
if (result > len - pos) then
result := len - pos;
move(data[pos+1], aBuffer^, result);
inc(pos, result);
end;

var
provider: TTestFiFo.IDataProvider;
begin
data := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
len := Length(data);
pos := 0;

provider := TTestFiFo.TNestedDataProvider.Create(@GiveData);
AssertEquals(len, fFiFo.Write(provider, len));
provider := nil;

SetLength(tmp, len);
AssertEquals(len, fFiFo.Read(PByte(@tmp[1]), len));
AssertEquals(0, fFiFo.Size);
AssertEquals('Data', 0, CompareStr(data, tmp));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.NestedConsumer;
var
pos: Integer;
len: Integer;
data: String;
tmp: String;

function TakeData(const aBuffer: PByte; aCount: Integer): Integer;
begin
result := aCount;
if (result > len - pos) then
result := len - pos;
move(aBuffer^, data[pos+1], result);
inc(pos, result);
end;

var
consumer: TTestFiFo.IDataConsumer;
begin
tmp := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
len := Length(tmp);
pos := 0;
AssertEquals(len, fFiFo.Write(@tmp[1], len));

SetLength(data, len);
consumer := TTestFiFo.TNestedDataConsumer.Create(@TakeData);
AssertEquals(len, fFiFo.Read(consumer, len));
consumer := nil;

AssertEquals(0, fFiFo.Size);
AssertEquals('Data', 0, CompareStr(data, tmp));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.StreamProvider;
var
s: TMemoryStream;
len: Integer;
buf1, buf2: String;
provider: TTestFiFo.IDataProvider;
begin
buf1 := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
len := Length(buf1);

s := TMemoryStream.Create;
try
s.Write(buf1[1], len);
s.Position := 0;
provider := TTestFiFo.TStreamDataProvider.Create(s);
AssertEquals(len, fFiFo.Write(provider, len));
provider := nil;

SetLength(buf2, len);
AssertEquals(len, fFiFo.Read(@buf2[1], len));
AssertEquals('Data', 0, CompareStr(buf1, buf2));
finally
FreeAndNil(s);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.StreamConsumer;
var
s: TMemoryStream;
len: Integer;
buf1, buf2: String;
consumer: TTestFiFo.IDataConsumer;
begin
buf1 := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
len := Length(buf1);

AssertEquals(len, fFiFo.Write(@buf1[1], len));

s := TMemoryStream.Create;
try
consumer := TTestFiFo.TStreamDataConsumer.Create(s);
AssertEquals(len, fFiFo.Read(consumer, len));
consumer := nil;

SetLength(buf2, len);
s.Position := 0;
s.Read(buf2[1], len);
AssertEquals('Data', 0, CompareStr(buf1, buf2));
finally
FreeAndNil(s);
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.RandomSizeTest;
const
MAX_LEN = 128;
MAX_REPEAT = 1024;

var
rBuf, wBuf: Word;
buf, tmp: array[0..MAX_LEN-1] of Word;
len, i, j: Integer;
begin
rBuf := 0;
wBuf := 0;
len := 1;
for i := 0 to MAX_REPEAT-1 do begin
for j := 0 to len-1 do begin
buf[j] := wBuf;
inc(wBuf);
end;
AssertEquals(SizeOf(Word) * len, fFiFo.Write(@buf[0], SizeOf(Word) * len));

AssertEquals(SizeOf(Word) * len, fFiFo.Peek(@tmp[0], SizeOf(Word) * len));
for j := 0 to len-1 do begin
AssertEquals(rBuf, tmp[j]);
inc(rBuf);
end;
AssertEquals(SizeOf(Word) * len, fFiFo.Discard(SizeOf(Word) * len));
AssertEquals(0, fFiFo.Size);

inc(len);
if (len >= MAX_LEN) then
len := 1;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.BigDataBlocks;
const
BUFFER_LEN = 1000;
REPEAT_COUNT = 50;
var
buf1, buf2: array[0..BUFFER_LEN-1] of Integer;
i, j, sz: Integer;
begin
for i := 0 to BUFFER_LEN-1 do
buf1[i] := i;

sz := 0;
for i := 0 to REPEAT_COUNT + 4 do begin
if (i < REPEAT_COUNT) then begin
AssertEquals(SizeOf(Integer) * BUFFER_LEN, fFiFo.Write(@buf1[0], SizeOf(Integer) * BUFFER_LEN));
inc(sz, SizeOf(Integer) * BUFFER_LEN);
AssertEquals(sz, fFiFo.Size);
end;

if (i >= 5) then begin
AssertEquals(SizeOf(Integer) * BUFFER_LEN, fFiFo.Read(@buf2[0], SizeOf(Integer) * BUFFER_LEN));
dec(sz, SizeOf(Integer) * BUFFER_LEN);
AssertEquals(sz, fFiFo.Size);
for j := 0 to BUFFER_LEN-1 do
AssertEquals(j, buf2[j]);
end;
end;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.WriteSmallBlocks;
var
pos: Integer;
len: Integer;
data: String;
tmp: String;

function GiveData(const aBuffer: PByte; aCount: Integer): Integer;
begin
result := aCount;
if (result > len - pos) then
result := len - pos;
if (result > 10) then
result := 10;
move(data[pos+1], aBuffer^, result);
inc(pos, result);
end;

var
provider: TTestFiFo.IDataProvider;
begin
data := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
len := Length(data);
pos := 0;

provider := TTestFiFo.TNestedDataProvider.Create(@GiveData);
AssertEquals(len, fFiFo.Write(provider, len));
provider := nil;

SetLength(tmp, len);
AssertEquals(len, fFiFo.Read(PByte(@tmp[1]), len));
AssertEquals(0, fFiFo.Size);
AssertEquals('Data', 0, CompareStr(data, tmp));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.ReadSmallBlocks;
var
pos: Integer;
len: Integer;
data: String;
tmp: String;

function TakeData(const aBuffer: PByte; aCount: Integer): Integer;
begin
result := aCount;
if (result > len - pos) then
result := len - pos;
if (result > 10) then
result := 10;
move(aBuffer^, data[pos+1], result);
inc(pos, result);
end;

var
consumer: TTestFiFo.IDataConsumer;
begin
tmp := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
len := Length(tmp);
pos := 0;
AssertEquals(len, fFiFo.Write(@tmp[1], len));

SetLength(data, len);
consumer := TTestFiFo.TNestedDataConsumer.Create(@TakeData);
AssertEquals(len, fFiFo.Read(consumer, len));
consumer := nil;

AssertEquals(0, fFiFo.Size);
AssertEquals('Data', 0, CompareStr(data, tmp));
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFoTest.WriteHalfPageReadAll;
const
REPEAT_COUNT = 10;
var
buf1: String;
i, sz: Integer;
p: Pointer;
begin
buf1 := 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab';
for i := 1 to REPEAT_COUNT do begin
AssertEquals('Write' + IntToStr(i), fFiFo.PageSize div 2, fFiFo.Write(@buf1[1], fFiFo.PageSize div 2));
sz := fFiFo.Size;
AssertEquals('Size' + IntToStr(i), fFiFo.PageSize div 2, sz);
p := GetMem(fFiFo.PageSize);
try
AssertEquals('Read' + IntToStr(i), sz, fFiFo.Read(p, fFiFo.PageSize));
Assert(CompareMem(p, @buf1[1], sz), 'Data' + IntToStr(i));
finally
Freemem(p);
end;
end;
end;

initialization


+ 144
- 60
uutlGenerics.pas Vedi File

@@ -433,15 +433,16 @@ type
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
generic TutlPagedDataFiFo<TData> = class
private type
PPage = ^TPage;
TPage = packed record
Next: PPage;
Data: array of TData;
ReadPos: Integer;
WritePos: Integer;
end;
PData = ^TData;
PPage = ^TPage;
TPageList = specialize TutlList<PPage>;
public type
PData = ^TData;

IDataProvider = interface(IUnknown)
function Give(const aBuffer: PData; aCount: Integer): Integer;
end;
@@ -450,6 +451,7 @@ type
function Take(const aBuffer: PData; aCount: Integer): Integer;
end;

// read from buffer, write to fifo
TDataProvider = class(TInterfacedObject, IDataProvider)
private
fData: PData;
@@ -460,6 +462,7 @@ type
constructor Create(const aData: PData; const aCount: Integer);
end;

// read from fifo, write to buffer
TDataConsumer = class(TInterfacedObject, IDataConsumer)
private
fData: PData;
@@ -470,20 +473,54 @@ type
constructor Create(const aData: PData; const aCount: Integer);
end;

// read from nested callback, write to fifo
TDataCallback = function(const aBuffer: PData; aCount: Integer): Integer is nested;
TNestedDataProvider = class(TInterfacedObject, IDataProvider)
private
fCallback: TDataCallback;
public
function Give(const aBuffer: PData; aCount: Integer): Integer;
constructor Create(const aCallback: TDataCallback);
end;

// read from fifo, write to nested callback
TNestedDataConsumer = class(TInterfacedObject, IDataConsumer)
private
fCallback: TDataCallback;
public
function Take(const aBuffer: PData; aCount: Integer): Integer;
constructor Create(const aCallback: TDataCallback);
end;

// read from stream, write to fifo
TStreamDataProvider = class(TInterfacedObject, IDataProvider)
private
fStream: TStream;
public
function Give(const aBuffer: PData; aCount: Integer): Integer;
constructor Create(const aStream: TStream);
end;

// read from fifo, write to stream
TStreamDataConsumer = class(TInterfacedObject, IDataConsumer)
private
fStream: TStream;
public
function Take(const aBuffer: PData; aCount: Integer): Integer;
constructor Create(const aStream: TStream);
end;

private
fPageSize: Integer;
fPages: TPageList;
fReadPage: PPage;
fWritePage: PPage;
fSize: Integer;

procedure InitReadPage(out aReadPage: PPage; out aDummyPage: TPage; out aPageIndex: Integer; const aMoveReadPos: Boolean);
function NextReadPage(out aReadPage: PPage; out aDummyPage: TPage; var aPageIndex: Integer; const aMoveReadPos: Boolean): Boolean;
protected
function WriteIntern(const aProvider: IDataProvider; aCount: Integer): Integer; virtual;
function ReadIntern(const aConsumer: IDataConsumer; aCount: Integer; const aMoveReadPos: Boolean): Integer; virtual;
public
property Size: Integer read fSize;
property Size: Integer read fSize;
property PageSize: Integer read fPageSize;

function Write(const aProvider: IDataProvider; const aCount: Integer): Integer; overload;
function Write(const aData: PData; const aCount: Integer): Integer; overload;
@@ -1817,48 +1854,72 @@ begin
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlPagedDataFiFo/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlPagedDataFiFo.TNestedDataProvider/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFo.InitReadPage(out aReadPage: PPage; out aDummyPage: TPage; out aPageIndex: Integer; const aMoveReadPos: Boolean);
function TutlPagedDataFiFo.TNestedDataProvider.Give(const aBuffer: PData; aCount: Integer): Integer;
begin
if not aMoveReadPos then begin
aPageIndex := 0;
aReadPage := nil;
if not Assigned(fReadPage) then
exit;
aDummyPage := fReadPage^; // copy page (only pointer to data is copied, because it's a dynamic array)
aReadPage := @aDummyPage;
end else
aReadPage := fReadPage;
result := fCallback(aBuffer, aCount);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlPagedDataFiFo.NextReadPage(out aReadPage: PPage; out aDummyPage: TPage; var aPageIndex: Integer; const aMoveReadPos: Boolean): Boolean;
constructor TutlPagedDataFiFo.TNestedDataProvider.Create(const aCallback: TDataCallback);
begin
result := false;
if not aMoveReadPos then begin
if (aPageIndex >= fPages.Count) then
exit;
aDummyPage := fPages[aPageIndex]^;
aReadPage := @aDummyPage;
inc(aPageIndex);
end else begin
if Assigned(fReadPage) then begin
Dispose(fReadPage);
fReadPage := nil;
end;
fReadPage := fPages.PopFirst;
if not Assigned(fReadPage) then
exit;
aReadPage := fReadPage;
end;
result := true;
inherited Create;
fCallback := aCallback;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlPagedDataFiFo.TNestedDataConsumer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlPagedDataFiFo.TNestedDataConsumer.Take(const aBuffer: PData; aCount: Integer): Integer;
begin
result := fCallback(aBuffer, aCount);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlPagedDataFiFo.TNestedDataConsumer.Create(const aCallback: TDataCallback);
begin
inherited Create;
fCallback := aCallback;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlPagedDataFiFo.TStreamDataProvider/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlPagedDataFiFo.TStreamDataProvider.Give(const aBuffer: PData; aCount: Integer): Integer;
begin
result := fStream.Read(aBuffer^, aCount);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlPagedDataFiFo.TStreamDataProvider.Create(const aStream: TStream);
begin
inherited Create;
fStream := aStream;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlPagedDataFiFo.TStreamDataConsumer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlPagedDataFiFo.TStreamDataConsumer.Take(const aBuffer: PData; aCount: Integer): Integer;
begin
result := fStream.Write(aBuffer^, aCount);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
constructor TutlPagedDataFiFo.TStreamDataConsumer.Create(const aStream: TStream);
begin
inherited Create;
fStream := aStream;
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TutlPagedDataFiFo/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function TutlPagedDataFiFo.WriteIntern(const aProvider: IDataProvider; aCount: Integer): Integer;
var
c, r: Integer;
p: PPage;
begin
if not Assigned(aProvider) then
raise EArgumentNil.Create('aProvider');
@@ -1866,12 +1927,16 @@ begin
result := 0;
while (aCount > 0) do begin
if not Assigned(fWritePage) or (fWritePage^.WritePos >= fPageSize) then begin
fWritePage := nil;
new(fWritePage);
fWritePage^.ReadPos := 0;
fWritePage^.WritePos := 0;
SetLength(fWritePage^.Data, fPageSize);
fPages.PushLast(fWritePage);
new(p);
p^.ReadPos := 0;
p^.WritePos := 0;
p^.Next := nil;
SetLength(p^.Data, fPageSize);
if Assigned(fWritePage) then
fWritePage^.Next := p;
fWritePage := p;
if not Assigned(fReadPage) then
fReadPage := fWritePage;
end;

c := fPageSize - fWritePage^.WritePos;
@@ -1884,8 +1949,8 @@ begin

inc(result, r);
inc(fWritePage^.WritePos, r);
dec(aCount, r);
inc(fSize, r);
dec(aCount, r);
end;
end;

@@ -1894,21 +1959,43 @@ function TutlPagedDataFiFo.ReadIntern(const aConsumer: IDataConsumer; aCount: In
var
ReadPage: PPage;
DummyPage: TPage;
PageIndex, c, r: Integer;
c, r: Integer;

begin
result := 0;
InitReadPage(ReadPage, DummyPage, PageIndex, aMoveReadPos);

if not Assigned(fReadPage) then
exit;

//init read page
if not aMoveReadPos then begin
DummyPage := fReadPage^; // copy page (data is not copied, because it's a dynamic array)
ReadPage := @DummyPage;
end else
ReadPage := fReadPage;

while (aCount > 0) do begin
if (not Assigned(ReadPage) or (ReadPage^.ReadPos >= fPageSize)) and
not NextReadPage(ReadPage, DummyPage, PageIndex, aMoveReadPos) then
exit;
if (ReadPage^.ReadPos >= fPageSize) then begin
if not Assigned(ReadPage^.Next) then
exit;
if aMoveReadPos then begin
if (fReadPage = fWritePage) then // write finished with page end, so reset WritePage wenn disposing ReadPage
fWritePage := nil;
fReadPage := fReadPage^.Next;
Dispose(ReadPage);
ReadPage := fReadPage;
end else
ReadPage^ := ReadPage^.Next^;
end;

c := fPageSize - ReadPage^.ReadPos;
c := ReadPage^.WritePos - ReadPage^.ReadPos;
if (c = 0) then
exit;
if (c > aCount) then
c := aCount;

if Assigned(aConsumer) then begin

r := aConsumer.Take(@ReadPage^.Data[ReadPage^.ReadPos], c);
if (r = 0) then
exit;
@@ -1976,12 +2063,13 @@ end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
procedure TutlPagedDataFiFo.Clear;
var
tmp: PPage;
begin
if Assigned(fReadPage) then
Dispose(fReadPage);
while (fPages.Count > 0) do begin
fReadPage := fPages.PopLast;
Dispose(fReadPage);
while Assigned(fReadPage) do begin
tmp := fReadPage;
fReadPage := tmp^.Next;
Dispose(tmp);
end;
fReadPage := nil;
fWritePage := nil;
@@ -1994,14 +2082,12 @@ begin
fReadPage := nil;
fWritePage := nil;
fPageSize := aPageSize;
fPages := TPageList.Create(false);
end;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
destructor TutlPagedDataFiFo.Destroy;
begin
Clear;
FreeAndNil(fPages);
inherited Destroy;
end;

@@ -2043,6 +2129,4 @@ begin
FreeAndNil(fLock);
end;


end.


Caricamento…
Annulla
Salva