@@ -37,55 +37,91 @@ | |||
<PackageName Value="FCL"/> | |||
</Item3> | |||
</RequiredPackages> | |||
<Units Count="12"> | |||
<Units Count="21"> | |||
<Unit0> | |||
<Filename Value="tests.lpr"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit0> | |||
<Unit1> | |||
<Filename Value="uutlQueueTests.pas"/> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit1> | |||
<Unit2> | |||
<Filename Value="uTestHelper.pas"/> | |||
<Filename Value="..\uutlArrayContainer.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit2> | |||
<Unit3> | |||
<Filename Value="uutlStackTests.pas"/> | |||
<Filename Value="..\uutlCommon.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit3> | |||
<Unit4> | |||
<Filename Value="uutlListTest.pas"/> | |||
<Filename Value="..\uutlExceptions.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit4> | |||
<Unit5> | |||
<Filename Value="..\uutlAlgorithm.pas"/> | |||
<Filename Value="..\uutlListBase.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit5> | |||
<Unit6> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Filename Value="uutlListTest.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit6> | |||
<Unit7> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Filename Value="uutlQueueTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit7> | |||
<Unit8> | |||
<Filename Value="..\uutlCommon.pas"/> | |||
<Filename Value="uutlStackTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit8> | |||
<Unit9> | |||
<Filename Value="uutlInterfaces.pas"/> | |||
<Filename Value="uTestHelper.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit9> | |||
<Unit10> | |||
<Filename Value="uutlHashSetTests.pas"/> | |||
<Filename Value="_uutlInterfaces.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit10> | |||
<Unit11> | |||
<Filename Value="uutlMapTests.pas"/> | |||
<Filename Value="..\uutlComparer.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit11> | |||
<Unit12> | |||
<Filename Value="..\uutlAlgorithm.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit12> | |||
<Unit13> | |||
<Filename Value="uutlHashSetTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit13> | |||
<Unit14> | |||
<Filename Value="uutlArrayTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit14> | |||
<Unit15> | |||
<Filename Value="uutlAlgorithmTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit15> | |||
<Unit16> | |||
<Filename Value="uutlMapTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit16> | |||
<Unit17> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit17> | |||
<Unit18> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit18> | |||
<Unit19> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit19> | |||
<Unit20> | |||
<Filename Value="..\uutlInterfaces.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
</Unit20> | |||
</Units> | |||
</ProjectOptions> | |||
<CompilerOptions> | |||
@@ -110,6 +146,11 @@ | |||
</Win32> | |||
</Options> | |||
</Linking> | |||
<Other> | |||
<CompilerMessages> | |||
<IgnoredMessages idx5024="True"/> | |||
</CompilerMessages> | |||
</Other> | |||
</CompilerOptions> | |||
<Debugging> | |||
<Exceptions Count="3"> | |||
@@ -4,7 +4,8 @@ program tests; | |||
uses | |||
Interfaces, Forms, GUITestRunner, | |||
uutlQueueTests, uutlStackTests, uutlListTest, uutlLinkedListTests, uutlHashSetTests, uutlMapTests; | |||
uutlStackTests, uutlQueueTests, uutlListTest, uutlHashSetTests, uutlArrayTests, | |||
uutlAlgorithmTests, uutlMapTests, uutlEnumeratorTests; | |||
{$R *.res} | |||
@@ -4,330 +4,402 @@ | |||
<PathDelim Value="\"/> | |||
<Version Value="9"/> | |||
<BuildModes Active="Default"/> | |||
<Units Count="26"> | |||
<Units Count="34"> | |||
<Unit0> | |||
<Filename Value="tests.lpr"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos X="7" Y="6"/> | |||
<UsageCount Value="39"/> | |||
<EditorIndex Value="3"/> | |||
<CursorPos X="5" Y="15"/> | |||
<UsageCount Value="30"/> | |||
<Loaded Value="True"/> | |||
</Unit0> | |||
<Unit1> | |||
<Filename Value="uutlQueueTests.pas"/> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos Y="12"/> | |||
<UsageCount Value="39"/> | |||
<EditorIndex Value="1"/> | |||
<TopLine Value="1045"/> | |||
<CursorPos X="25" Y="1060"/> | |||
<UsageCount Value="30"/> | |||
<Loaded Value="True"/> | |||
</Unit1> | |||
<Unit2> | |||
<Filename Value="uTestHelper.pas"/> | |||
<Filename Value="..\uutlArrayContainer.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos X="16" Y="12"/> | |||
<UsageCount Value="39"/> | |||
<TopLine Value="24"/> | |||
<CursorPos X="14" Y="38"/> | |||
<UsageCount Value="30"/> | |||
</Unit2> | |||
<Unit3> | |||
<Filename Value="uutlStackTests.pas"/> | |||
<Filename Value="..\uutlCommon.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos X="75" Y="17"/> | |||
<UsageCount Value="39"/> | |||
<TopLine Value="3"/> | |||
<CursorPos X="29" Y="8"/> | |||
<UsageCount Value="30"/> | |||
</Unit3> | |||
<Unit4> | |||
<Filename Value="uutlListTest.pas"/> | |||
<Filename Value="..\uutlExceptions.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos X="27" Y="16"/> | |||
<UsageCount Value="39"/> | |||
<TopLine Value="9"/> | |||
<CursorPos X="35" Y="14"/> | |||
<UsageCount Value="30"/> | |||
</Unit4> | |||
<Unit5> | |||
<Filename Value="..\uutlAlgorithm.pas"/> | |||
<Filename Value="..\uutlListBase.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="13"/> | |||
<CursorPos X="68" Y="29"/> | |||
<UsageCount Value="33"/> | |||
<EditorIndex Value="4"/> | |||
<CursorPos X="23" Y="9"/> | |||
<UsageCount Value="30"/> | |||
<Loaded Value="True"/> | |||
</Unit5> | |||
<Unit6> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Filename Value="uutlListTest.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="2"/> | |||
<TopLine Value="267"/> | |||
<CursorPos X="29" Y="284"/> | |||
<UsageCount Value="32"/> | |||
<Loaded Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="357"/> | |||
<CursorPos X="7" Y="376"/> | |||
<UsageCount Value="30"/> | |||
</Unit6> | |||
<Unit7> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Filename Value="uutlQueueTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<IsVisibleTab Value="True"/> | |||
<TopLine Value="225"/> | |||
<CursorPos X="26" Y="245"/> | |||
<EditorIndex Value="-1"/> | |||
<UsageCount Value="30"/> | |||
<Loaded Value="True"/> | |||
</Unit7> | |||
<Unit8> | |||
<Filename Value="..\uutlCommon.pas"/> | |||
<Filename Value="uutlStackTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="21"/> | |||
<CursorPos Y="41"/> | |||
<UsageCount Value="28"/> | |||
<CursorPos X="3" Y="9"/> | |||
<UsageCount Value="30"/> | |||
</Unit8> | |||
<Unit9> | |||
<Filename Value="uutlInterfaces.pas"/> | |||
<Filename Value="uTestHelper.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="1"/> | |||
<TopLine Value="118"/> | |||
<CursorPos X="28" Y="139"/> | |||
<UsageCount Value="27"/> | |||
<Loaded Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<CursorPos X="3" Y="12"/> | |||
<UsageCount Value="30"/> | |||
</Unit9> | |||
<Unit10> | |||
<Filename Value="uutlHashSetTests.pas"/> | |||
<Filename Value="_uutlInterfaces.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="90"/> | |||
<CursorPos X="29" Y="115"/> | |||
<UsageCount Value="27"/> | |||
<CursorPos X="42" Y="6"/> | |||
<UsageCount Value="30"/> | |||
</Unit10> | |||
<Unit11> | |||
<Filename Value="..\test.lpr"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="55"/> | |||
<CursorPos Y="72"/> | |||
<UsageCount Value="9"/> | |||
<Filename Value="..\uutlComparer.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="6"/> | |||
<CursorPos X="25" Y="13"/> | |||
<UsageCount Value="30"/> | |||
<Loaded Value="True"/> | |||
</Unit11> | |||
<Unit12> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\TestFramework.pas"/> | |||
<Filename Value="..\uutlAlgorithm.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="427"/> | |||
<CursorPos X="3" Y="394"/> | |||
<UsageCount Value="13"/> | |||
<TopLine Value="43"/> | |||
<CursorPos X="33" Y="55"/> | |||
<UsageCount Value="30"/> | |||
</Unit12> | |||
<Unit13> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\FPCUnitCompatibleInterface.inc"/> | |||
<EditorIndex Value="3"/> | |||
<TopLine Value="54"/> | |||
<CursorPos Y="69"/> | |||
<UsageCount Value="14"/> | |||
<Loaded Value="True"/> | |||
<Filename Value="uutlHashSetTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<UsageCount Value="30"/> | |||
</Unit13> | |||
<Unit14> | |||
<Filename Value="G:\Eigene Datein\Projekte\Delphi\TotoStarRedesign\utils\uutlGenerics.pas"/> | |||
<Filename Value="uutlArrayTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="527"/> | |||
<UsageCount Value="12"/> | |||
<TopLine Value="118"/> | |||
<CursorPos X="29" Y="137"/> | |||
<UsageCount Value="29"/> | |||
</Unit14> | |||
<Unit15> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\objpas\fgl.pp"/> | |||
<Filename Value="uutlAlgorithmTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="544"/> | |||
<CursorPos X="15" Y="562"/> | |||
<UsageCount Value="14"/> | |||
<CursorPos Y="77"/> | |||
<UsageCount Value="29"/> | |||
</Unit15> | |||
<Unit16> | |||
<Filename Value="G:\Eigene Datein\Projekte\Delphi\TotoStarRedesign\utils\uutlInterfaces.pas"/> | |||
<Filename Value="..\..\Utils\uutlGenerics2.pas"/> | |||
<IsVisibleTab Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="69"/> | |||
<CursorPos Y="88"/> | |||
<UsageCount Value="14"/> | |||
<TopLine Value="1902"/> | |||
<CursorPos Y="1905"/> | |||
<UsageCount Value="11"/> | |||
<Loaded Value="True"/> | |||
</Unit16> | |||
<Unit17> | |||
<Filename Value="..\uutlExceptions.pas"/> | |||
<Filename Value="..\..\Utils\uutlCommon2.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<CursorPos X="3" Y="15"/> | |||
<UsageCount Value="10"/> | |||
<TopLine Value="9"/> | |||
<CursorPos X="15" Y="26"/> | |||
<UsageCount Value="11"/> | |||
</Unit17> | |||
<Unit18> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\inc\objpash.inc"/> | |||
<Filename Value="..\..\Utils\uutlExceptions.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="437"/> | |||
<CursorPos X="5" Y="453"/> | |||
<TopLine Value="77"/> | |||
<CursorPos X="3" Y="18"/> | |||
<UsageCount Value="9"/> | |||
</Unit18> | |||
<Unit19> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\inc\objpas.inc"/> | |||
<Filename Value="..\..\Utils\tests\uutlInterfaces2.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="999"/> | |||
<CursorPos X="19" Y="1017"/> | |||
<UsageCount Value="9"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="49"/> | |||
<CursorPos X="35" Y="60"/> | |||
<UsageCount Value="11"/> | |||
</Unit19> | |||
<Unit20> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\TestFrameworkIfaces.pas"/> | |||
<Filename Value="..\..\Utils\uutlComparer.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="36"/> | |||
<CursorPos X="3" Y="51"/> | |||
<UsageCount Value="9"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="84"/> | |||
<CursorPos X="28" Y="28"/> | |||
<UsageCount Value="11"/> | |||
</Unit20> | |||
<Unit21> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\objpas\sysutils\intfh.inc"/> | |||
<Filename Value="..\..\Utils\uutlAlgorithm2.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="6"/> | |||
<CursorPos X="26" Y="18"/> | |||
<UsageCount Value="9"/> | |||
<TopLine Value="66"/> | |||
<CursorPos X="5" Y="93"/> | |||
<UsageCount Value="11"/> | |||
</Unit21> | |||
<Unit22> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\objpas\sysutils\sysuintf.inc"/> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\objpas\objpas.pp"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="15"/> | |||
<CursorPos X="3" Y="17"/> | |||
<UsageCount Value="9"/> | |||
<TopLine Value="62"/> | |||
<CursorPos X="5" Y="77"/> | |||
<UsageCount Value="13"/> | |||
</Unit22> | |||
<Unit23> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\fpc\3.1.1\source\rtl\inc\systemh.inc"/> | |||
<Filename Value="..\..\Utils\uutlInterfaces.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="770"/> | |||
<CursorPos X="11" Y="785"/> | |||
<UsageCount Value="11"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="31"/> | |||
<CursorPos X="22" Y="45"/> | |||
<UsageCount Value="12"/> | |||
</Unit23> | |||
<Unit24> | |||
<Filename Value="G:\Eigene Datein\Projekte\Delphi\TotoStarRedesign\utils\uutlObservableGenerics.pas"/> | |||
<Filename Value="G:\Eigene Datein\Projekte\_Active Projekte\TotoStarRedesign\utils\uutlAlgorithm.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="115"/> | |||
<CursorPos X="32" Y="101"/> | |||
<UsageCount Value="10"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="48"/> | |||
<CursorPos X="45" Y="56"/> | |||
<UsageCount Value="11"/> | |||
</Unit24> | |||
<Unit25> | |||
<Filename Value="uutlMapTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos X="9" Y="24"/> | |||
<UsageCount Value="23"/> | |||
<TopLine Value="65"/> | |||
<CursorPos X="60" Y="75"/> | |||
<UsageCount Value="28"/> | |||
</Unit25> | |||
<Unit26> | |||
<Filename Value="..\..\Utils\uutlEnumerator2.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="126"/> | |||
<CursorPos X="22" Y="128"/> | |||
<UsageCount Value="10"/> | |||
</Unit26> | |||
<Unit27> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<TopLine Value="76"/> | |||
<CursorPos X="39" Y="90"/> | |||
<UsageCount Value="27"/> | |||
<Loaded Value="True"/> | |||
</Unit27> | |||
<Unit28> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="2"/> | |||
<TopLine Value="247"/> | |||
<CursorPos X="29" Y="262"/> | |||
<UsageCount Value="27"/> | |||
<Loaded Value="True"/> | |||
</Unit28> | |||
<Unit29> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\FPCUnitCompatibleInterface.inc"/> | |||
<EditorIndex Value="-1"/> | |||
<TopLine Value="90"/> | |||
<CursorPos X="16" Y="97"/> | |||
<UsageCount Value="10"/> | |||
</Unit29> | |||
<Unit30> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\TestFramework.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<WindowIndex Value="1"/> | |||
<TopLine Value="2964"/> | |||
<CursorPos Y="2979"/> | |||
<UsageCount Value="9"/> | |||
</Unit30> | |||
<Unit31> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<EditorIndex Value="7"/> | |||
<TopLine Value="19"/> | |||
<CursorPos X="40" Y="62"/> | |||
<UsageCount Value="23"/> | |||
<Loaded Value="True"/> | |||
</Unit31> | |||
<Unit32> | |||
<Filename Value="..\uutlInterfaces.pas"/> | |||
<IsPartOfProject Value="True"/> | |||
<IsVisibleTab Value="True"/> | |||
<EditorIndex Value="5"/> | |||
<CursorPos X="21" Y="10"/> | |||
<UsageCount Value="23"/> | |||
<Loaded Value="True"/> | |||
</Unit32> | |||
<Unit33> | |||
<Filename Value="..\internal_uutlInterfaces.pas"/> | |||
<EditorIndex Value="-1"/> | |||
<CursorPos Y="11"/> | |||
<UsageCount Value="10"/> | |||
</Unit33> | |||
</Units> | |||
<JumpHistory Count="29" HistoryIndex="28"> | |||
<JumpHistory Count="30" HistoryIndex="29"> | |||
<Position1> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1485" TopLine="1470"/> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<Caret Line="52" Column="24" TopLine="29"/> | |||
</Position1> | |||
<Position2> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1486" TopLine="1470"/> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<Caret Line="71" Column="17" TopLine="58"/> | |||
</Position2> | |||
<Position3> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1487" TopLine="1470"/> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<Caret Line="78" TopLine="63"/> | |||
</Position3> | |||
<Position4> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1217" TopLine="1202"/> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<Caret Line="69" Column="43" TopLine="55"/> | |||
</Position4> | |||
<Position5> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1219" TopLine="1202"/> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<Caret Line="144" Column="11" TopLine="123"/> | |||
</Position5> | |||
<Position6> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1220" TopLine="1202"/> | |||
<Filename Value="..\uutlFilter.pas"/> | |||
<Caret Line="60" Column="58" TopLine="43"/> | |||
</Position6> | |||
<Position7> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1221" TopLine="1202"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="156" Column="82" TopLine="133"/> | |||
</Position7> | |||
<Position8> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="478" Column="83" TopLine="464"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="478" Column="12" TopLine="453"/> | |||
</Position8> | |||
<Position9> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="71" Column="25" TopLine="60"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="151" Column="30" TopLine="136"/> | |||
</Position9> | |||
<Position10> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="97" Column="60" TopLine="74"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="476" Column="44" TopLine="453"/> | |||
</Position10> | |||
<Position11> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="93" Column="77" TopLine="74"/> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<Caret Line="26" Column="37" TopLine="9"/> | |||
</Position11> | |||
<Position12> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="73" Column="15" TopLine="69"/> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<Caret Line="273" Column="19" TopLine="244"/> | |||
</Position12> | |||
<Position13> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="123" Column="35" TopLine="105"/> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<Caret Line="263" Column="75" TopLine="248"/> | |||
</Position13> | |||
<Position14> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="641" Column="24" TopLine="618"/> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<Caret Line="253" Column="35" TopLine="248"/> | |||
</Position14> | |||
<Position15> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="130" Column="40" TopLine="111"/> | |||
<Filename Value="uutlEnumeratorTests.pas"/> | |||
<Caret Line="262" Column="29" TopLine="247"/> | |||
</Position15> | |||
<Position16> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="138" Column="34" TopLine="111"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="158" Column="41" TopLine="137"/> | |||
</Position16> | |||
<Position17> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="265" Column="24" TopLine="241"/> | |||
<Filename Value="..\uutlInterfaces.pas"/> | |||
<Caret Line="44" Column="39" TopLine="29"/> | |||
</Position17> | |||
<Position18> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="171" Column="30" TopLine="150"/> | |||
<Filename Value="..\uutlInterfaces.pas"/> | |||
<Caret Line="48" Column="51" TopLine="28"/> | |||
</Position18> | |||
<Position19> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="188" Column="23" TopLine="173"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="37" Column="39" TopLine="22"/> | |||
</Position19> | |||
<Position20> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="194" Column="22" TopLine="173"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="90" Column="39" TopLine="77"/> | |||
</Position20> | |||
<Position21> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="266" Column="49" TopLine="247"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="343" Column="27" TopLine="338"/> | |||
</Position21> | |||
<Position22> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="39" Column="32" TopLine="24"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="344" Column="11" TopLine="338"/> | |||
</Position22> | |||
<Position23> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="282" Column="29" TopLine="259"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="348" Column="19" TopLine="338"/> | |||
</Position23> | |||
<Position24> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="96" Column="14" TopLine="81"/> | |||
<Caret Line="393" Column="20" TopLine="373"/> | |||
</Position24> | |||
<Position25> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="19" Column="5" TopLine="3"/> | |||
<Caret Line="1369" Column="30" TopLine="1347"/> | |||
</Position25> | |||
<Position26> | |||
<Filename Value="uutlInterfaces.pas"/> | |||
<Caret Line="169" Column="35" TopLine="151"/> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="9" Column="92"/> | |||
</Position26> | |||
<Position27> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="279" Column="78" TopLine="263"/> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="401" Column="48" TopLine="377"/> | |||
</Position27> | |||
<Position28> | |||
<Filename Value="C:\Zusatzprogramme\Lazarus\components\fptest\src\FPCUnitCompatibleInterface.inc"/> | |||
<Caret Line="69" TopLine="54"/> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1352" Column="15" TopLine="1337"/> | |||
</Position28> | |||
<Position29> | |||
<Filename Value="uutlLinkedListTests.pas"/> | |||
<Caret Line="290" Column="27" TopLine="264"/> | |||
<Filename Value="..\uutlEnumerator.pas"/> | |||
<Caret Line="90" Column="39" TopLine="76"/> | |||
</Position29> | |||
<Position30> | |||
<Filename Value="..\uutlGenerics.pas"/> | |||
<Caret Line="1060" Column="25" TopLine="1045"/> | |||
</Position30> | |||
</JumpHistory> | |||
</ProjectSession> | |||
<Debugging> | |||
<Watches Count="1"> | |||
<Item1> | |||
<Expression Value="aElement^.data"/> | |||
<Expression Value="fCurrentSkip"/> | |||
</Item1> | |||
</Watches> | |||
</Debugging> | |||
@@ -0,0 +1,126 @@ | |||
unit uutlAlgorithmTests; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, TestFramework, | |||
uutlComparer; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
TutlAlgorithmTest = class(TTestCase) | |||
published | |||
procedure BinarySearch; | |||
procedure QuickSort; | |||
end; | |||
implementation | |||
uses | |||
uutlGenerics, uutlAlgorithm; | |||
type | |||
TIntArray = specialize TutlArray<Integer>; | |||
TQuickSort = specialize TutlQuickSort<Integer>; | |||
TBinarySearch = specialize TutlBinarySearch<Integer>; | |||
TIntComparer = specialize TutlComparer<Integer>; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlAlgorithmTest///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlAlgorithmTest.BinarySearch; | |||
var | |||
arr: TIntArray; | |||
index: Integer; | |||
ret: Boolean; | |||
begin | |||
arr := TIntArray.Create; | |||
arr.Count := 10; | |||
arr[0] := 1; | |||
arr[1] := 4; | |||
arr[2] := 5; | |||
arr[3] := 6; | |||
arr[4] := 10; | |||
arr[5] := 11; | |||
arr[6] := 13; | |||
arr[7] := 20; | |||
arr[8] := 21; | |||
arr[9] := 22; | |||
ret := TBinarySearch.Search(arr, TIntComparer.Create, 4, index); | |||
AssertTrue (ret); | |||
AssertEquals(1, index); | |||
ret := TBinarySearch.Search(arr, TIntComparer.Create, 7, index); | |||
AssertFalse (ret); | |||
AssertEquals(4, index); | |||
ret := TBinarySearch.Search(arr, TIntComparer.Create, 13, index); | |||
AssertTrue (ret); | |||
AssertEquals(6, index); | |||
ret := TBinarySearch.Search(arr, TIntComparer.Create, 19, index); | |||
AssertFalse (ret); | |||
AssertEquals(7, index); | |||
ret := TBinarySearch.Search(arr, TIntComparer.Create, 25, index); | |||
AssertFalse (ret); | |||
AssertEquals(10, index); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlAlgorithmTest.QuickSort; | |||
var | |||
arr: TIntArray; | |||
begin | |||
arr := TIntArray.Create; | |||
arr.Count := 20; | |||
arr[ 0] := 134; | |||
arr[ 1] := 314; | |||
arr[ 2] := 721; | |||
arr[ 3] := 672; | |||
arr[ 4] := 831; | |||
arr[ 5] := 163; | |||
arr[ 6] := 126; | |||
arr[ 7] := 732; | |||
arr[ 8] := 175; | |||
arr[ 9] := 274; | |||
arr[10] := 462; | |||
arr[11] := 627; | |||
arr[12] := 633; | |||
arr[13] := 672; | |||
arr[14] := 752; | |||
arr[15] := 367; | |||
arr[16] := 263; | |||
arr[17] := 456; | |||
arr[18] := 678; | |||
arr[19] := 832; | |||
TQuickSort.Sort(arr, TIntComparer.Create); | |||
AssertEquals(126, arr[ 0]); | |||
AssertEquals(134, arr[ 1]); | |||
AssertEquals(163, arr[ 2]); | |||
AssertEquals(175, arr[ 3]); | |||
AssertEquals(263, arr[ 4]); | |||
AssertEquals(274, arr[ 5]); | |||
AssertEquals(314, arr[ 6]); | |||
AssertEquals(367, arr[ 7]); | |||
AssertEquals(456, arr[ 8]); | |||
AssertEquals(462, arr[ 9]); | |||
AssertEquals(627, arr[10]); | |||
AssertEquals(633, arr[11]); | |||
AssertEquals(672, arr[12]); | |||
AssertEquals(672, arr[13]); | |||
AssertEquals(678, arr[14]); | |||
AssertEquals(721, arr[15]); | |||
AssertEquals(732, arr[16]); | |||
AssertEquals(752, arr[17]); | |||
AssertEquals(831, arr[18]); | |||
AssertEquals(832, arr[19]); | |||
end; | |||
initialization | |||
RegisterTest(TutlAlgorithmTest.Suite); | |||
end. | |||
@@ -0,0 +1,151 @@ | |||
unit uutlArrayTests; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, TestFramework, | |||
uutlGenerics; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
TIntArray = specialize TutlArray<Integer>; | |||
TutlArrayTest = class(TTestCase) | |||
published | |||
procedure Prop_Get_Count; | |||
procedure Prop_Set_Count; | |||
procedure Prop_Get_Items; | |||
procedure Prop_Set_Items; | |||
procedure Prop_Get_Data; | |||
procedure Prop_Set_Data; | |||
procedure Meth_Ctor; | |||
end; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlArrayTest///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Prop_Get_Count; | |||
var | |||
arr: TIntArray; | |||
begin | |||
arr := TIntArray.Create; | |||
try | |||
AssertEquals(0, arr.Count); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Prop_Set_Count; | |||
var | |||
arr: TIntArray; | |||
begin | |||
arr := TIntArray.Create; | |||
try | |||
AssertEquals(0, arr.Count); | |||
arr.Count := 1; | |||
AssertEquals(1, arr.Count); | |||
arr.Count := 5; | |||
AssertEquals(5, arr.Count); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Prop_Get_Items; | |||
var | |||
arr: TIntArray; | |||
begin | |||
arr := TIntArray.Create; | |||
try | |||
arr.Count := 1; | |||
AssertEquals(0, arr[0]); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Prop_Set_Items; | |||
var | |||
arr: TIntArray; | |||
begin | |||
arr := TIntArray.Create; | |||
try | |||
arr.Count := 3; | |||
arr[0] := 1; | |||
arr[1] := 3; | |||
arr[2] := 5; | |||
AssertEquals(1, arr[0]); | |||
AssertEquals(3, arr[1]); | |||
AssertEquals(5, arr[2]); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Prop_Get_Data; | |||
var | |||
arr: TIntArray; | |||
data: TIntArray.TData; | |||
begin | |||
arr := TIntArray.Create; | |||
try | |||
arr.Count := 3; | |||
arr[0] := 1; | |||
arr[1] := 3; | |||
arr[2] := 5; | |||
data := arr.Data; | |||
AssertEquals(3, Length(data)); | |||
AssertEquals(1, data[0]); | |||
AssertEquals(3, data[1]); | |||
AssertEquals(5, data[2]); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Prop_Set_Data; | |||
var | |||
arr: TIntArray; | |||
data: TIntArray.TData; | |||
begin | |||
arr := TIntArray.Create; | |||
try | |||
SetLength(data, 5); | |||
arr.Data := data; | |||
AssertEquals(5, arr.Count); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayTest.Meth_Ctor; | |||
var | |||
arr: TIntArray; | |||
data: TIntArray.TData; | |||
begin | |||
SetLength(data, 5); | |||
arr := TIntArray.Create(data); | |||
try | |||
AssertEquals(5, arr.Count); | |||
finally | |||
FreeAndNil(arr); | |||
end; | |||
end; | |||
initialization | |||
RegisterTest(TutlArrayTest.Suite); | |||
end. | |||
@@ -0,0 +1,281 @@ | |||
unit uutlEnumeratorTests; | |||
{$mode objfpc}{$H+} | |||
{$modeswitch nestedprocvars} | |||
interface | |||
uses | |||
Classes, SysUtils, TestFramework, | |||
uutlEnumerator; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
TutlEnumeratorTests = class(TTestCase) | |||
published | |||
procedure ArrayEnumerator; | |||
procedure ArrayEnumerator_Reverse; | |||
procedure ArrayEnumerator_Count; | |||
procedure ArrayEnumerator_Skip; | |||
procedure ArrayEnumerator_Take; | |||
procedure ArrayEnumerator_Skip_Reverse; | |||
procedure ArrayEnumerator_Take_Reverse; | |||
procedure ArrayEnumerator_Reverse_Skip; | |||
procedure ArrayEnumerator_Reverse_Take; | |||
procedure ArrayEnumerator_Where; | |||
procedure ArrayEnumerator_Select; | |||
end; | |||
implementation | |||
uses | |||
uutlFilter; | |||
type | |||
TIntCalbackFilter = specialize TutlCalbackFilter<Integer>; | |||
TIntArrEnumerator = specialize TutlArrayEnumerator<Integer>; | |||
TFloatArrEnumerator = specialize TutlArrayEnumerator<Single>; | |||
function CreateArrayEnumerator(const aSize: Integer): TIntArrEnumerator.IEnumerator; | |||
var | |||
arr: array of Integer; | |||
i: Integer; | |||
begin | |||
SetLength(arr, aSize); | |||
for i := low(arr) to high(arr) do | |||
arr[i] := i + 1; | |||
result := TIntArrEnumerator.Create(arr); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlEnumeratorTests/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(5); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(1, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(3, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(5, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Reverse; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(5) | |||
.Reverse; | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(5, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(3, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(1, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Count; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(5); | |||
AssertEquals(5, e.Count); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Skip; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Skip(5); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(6, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(7, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(8, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(9, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(10, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Take; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Take(5); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(1, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(3, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(5, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Skip_Reverse; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Skip(5) | |||
.Reverse; | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(10, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(9, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(8, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(7, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(6, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Take_Reverse; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Take(5) | |||
.Reverse; | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(5, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(3, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(1, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Reverse_Skip; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Reverse | |||
.Skip(5); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(5, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(3, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(1, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Reverse_Take; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Reverse | |||
.Take(5); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(10, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(9, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(8, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(7, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(6, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Where; | |||
function IsEven(constref i: Integer): Boolean; | |||
begin | |||
result := (i mod 2) = 0; | |||
end; | |||
var | |||
e: TIntArrEnumerator.IEnumerator; | |||
begin | |||
e := CreateArrayEnumerator(10) | |||
.Where(TIntCalbackFilter.Create(@IsEven)); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(6, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(8, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(10, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlEnumeratorTests.ArrayEnumerator_Select; | |||
function ConvertToFloat(constref a: Integer): Single; | |||
begin | |||
result := Single(a); | |||
end; | |||
var | |||
e: TFloatArrEnumerator.IEnumerator; | |||
begin | |||
e := specialize TutlSelectEnumerator<Integer, Single>.Create( | |||
CreateArrayEnumerator(5), | |||
specialize TutlCalbackSelector<Integer, Single>.Create(@ConvertToFloat)); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(1.0, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(2.0, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(3.0, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(4.0, e.Current); | |||
AssertTrue (e.MoveNext); | |||
AssertEquals(5.0, e.Current); | |||
AssertFalse (e.MoveNext); | |||
end; | |||
initialization | |||
RegisterTest(TutlEnumeratorTests.Suite); | |||
end. | |||
@@ -1,408 +0,0 @@ | |||
unit uutlInterfaces; | |||
{$mode objfpc}{$H+} | |||
{$modeswitch nestedprocvars} | |||
interface | |||
uses | |||
Classes, SysUtils; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Container///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlEnumerator<T> = interface(specialize IEnumerator<T>) | |||
['{134FAC2F-3F23-4BD8-88FB-4B3BD2253E03}'] | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlEnumerable<T> = interface(specialize IEnumerable<T>) | |||
['{B6B43A0E-754C-43D0-829A-6632F922A2DE}'] | |||
function GetUtlEnumerator: specialize IutlEnumerator<T>; | |||
property Enumerator: specialize IutlEnumerator<T> read GetUtlEnumerator; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlReadOnlyIndexer<T> = interface(IUnknown) | |||
['{9E502CF8-3223-4784-8DB7-614187FFFE68}'] | |||
function GetCount: Integer; | |||
function GetItem(const aIndex: Integer): T; | |||
property Count: Integer read GetCount; | |||
property Items[const aIndex: Integer]: T read GetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlIndexer<T> = interface(specialize IutlReadOnlyIndexer<T>) | |||
['{4CA50BE2-A1DF-48BE-9E83-0C94015BA873}'] | |||
procedure SetItem(const aIndex: Integer; aItem: T); | |||
property Items[const aIndex: Integer]: T read GetItem write SetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Comparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlEqualityComparer<T> = interface(IUnknown) | |||
['{C0FB90CC-D071-490F-BFEE-BAA5C94D1A5B}'] | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlComparer<T> = interface(specialize IutlEqualityComparer<T>) | |||
['{7D2EC014-2878-4F60-9E43-4CFB54268995}'] | |||
function Compare(constref i1, i2: T): Integer; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlEqualityComparer<T> = class(TInterfacedObject, specialize IutlEqualityComparer<T>) | |||
public | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlEqualityCompareEvent<T> = function(constref i1, i2: T): Boolean; | |||
generic TutlEqualityCompareEventO<T> = function(constref i1, i2: T): Boolean of object; | |||
generic TutlEqualityCompareEventN<T> = function(constref i1, i2: T): Boolean is nested; | |||
generic TutlCalbackEqualityComparer<T> = class(TInterfacedObject, specialize IutlEqualityComparer<T>) | |||
private type | |||
TEqualityCompareEventType = (eetNormal, eetObject, eetNested); | |||
public type | |||
TCompareEvent = specialize TutlEqualityCompareEvent<T>; | |||
TCompareEventO = specialize TutlEqualityCompareEventO<T>; | |||
TCompareEventN = specialize TutlEqualityCompareEventN<T>; | |||
strict private | |||
fType: TEqualityCompareEventType; | |||
fEvent: TCompareEvent; | |||
fEventO: TCompareEventO; | |||
fEventN: TCompareEventN; | |||
public | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
constructor Create(const aEvent: TCompareEvent); | |||
constructor Create(const aEvent: TCompareEventO); | |||
constructor Create(const aEvent: TCompareEventN); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlComparer<T> = class(specialize TutlEqualityComparer<T>, specialize IutlComparer<T>) | |||
public | |||
function Compare(constref i1, i2: T): Integer; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlCompareEvent<T> = function(constref i1, i2: T): Integer; | |||
generic TutlCompareEventO<T> = function(constref i1, i2: T): Integer of object; | |||
generic TutlCompareEventN<T> = function(constref i1, i2: T): Integer is nested; | |||
generic TutlCallbackComparer<T> = class(TInterfacedObject, specialize IutlComparer<T>) | |||
private type | |||
TCompareEventType = (cetNormal, cetObject, cetNested); | |||
public type | |||
TCompareEvent = specialize TutlCompareEvent<T>; | |||
TCompareEventO = specialize TutlCompareEventO<T>; | |||
TCompareEventN = specialize TutlCompareEventN<T>; | |||
strict private | |||
fType: TCompareEventType; | |||
fEvent: TCompareEvent; | |||
fEventO: TCompareEventO; | |||
fEventN: TCompareEventN; | |||
public | |||
function Compare(constref i1, i2: T): Integer; | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
constructor Create(const aEvent: TCompareEvent); | |||
constructor Create(const aEvent: TCompareEventO); | |||
constructor Create(const aEvent: TCompareEventN); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Iterators///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
IutlIterator = interface(IUnknown) | |||
['{327E7628-C9D8-4C47-9630-E979D9C3293D}'] | |||
function MoveNext: Boolean; | |||
function Clone: IutlIterator; | |||
function Equals(const aOther: IutlIterator): Boolean; | |||
function GetIsValid: Boolean; | |||
property IsValid: Boolean read GetIsValid; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
IutlBidirectionalIterator = interface(IutlIterator) | |||
['{31D1E828-52CC-467F-8254-2C1384B28DEE}'] | |||
function MovePrev: Boolean; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
IutlRandomAccessIterator = interface(IutlBidirectionalIterator) | |||
['{AE06BAB6-BB17-4E46-AE88-583EB853233E}'] | |||
function Increment (const aCount: Integer): Boolean; | |||
function Decrement (const aCount: Integer): Boolean; | |||
function Compare (constref aOther: IutlRandomAccessIterator): Integer; | |||
function GetDifference(constref aOther: IutlRandomAccessIterator): Integer; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlInputIterator<T> = interface(IutlIterator) | |||
['{BD4ED39B-2BBA-41F7-BDC7-E1B45F41AA84}'] | |||
function GetItem: T; | |||
property Item: T read GetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlOutputIterator<T> = interface(IutlIterator) | |||
['{132642C1-5235-4450-8956-2092D3F2F83D}'] | |||
procedure SetItem(aValue: T); | |||
property Item: T write SetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlInputOutputIterator<T> = interface(IutlIterator) | |||
['{5367DA1F-F98C-4EE7-A454-E8978E2A9B46}'] | |||
function GetItem: T; | |||
procedure SetItem(aValue: T); | |||
property Item: T read GetItem write SetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlBidirectionalInputIterator<T> = interface(IutlBidirectionalIterator) | |||
['{B2423828-F187-4620-8DA2-9C4EF68B81E3}'] | |||
function GetItem: T; | |||
property Item: T read GetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlBidirectionalOutputIterator<T> = interface(IutlBidirectionalIterator) | |||
['{1A13E581-200B-41E7-BC7D-9AD5192DEF0F}'] | |||
procedure SetItem(aValue: T); | |||
property Item: T write SetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlBidirectionalInputOutputIterator<T> = interface(IutlBidirectionalIterator) | |||
['{BD8A6D08-7980-45D1-86A6-838402F5CBA6}'] | |||
function GetItem: T; | |||
procedure SetItem(aItem: T); | |||
property Item: T read GetItem write SetItem; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlRandomAccessInputIterator<T> = interface(IutlRandomAccessIterator) | |||
['{47880DCC-49D4-45C7-90CB-D8E915B7CB0D}'] | |||
function GetItem: T; | |||
function GetItems(const aIndex: Integer): T; | |||
property Item: T read GetItem; | |||
property Items[const aIndex: Integer]: T read GetItems; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlRandomAccessOutputIterator<T> = interface(IutlRandomAccessIterator) | |||
['{E768DA58-E666-47F1-B7D8-61EB6C33C379}'] | |||
procedure SetItem(aValue: T); | |||
procedure SetItems(const aIndex: Integer; aValue: T); | |||
property Item: T write SetItem; | |||
property Items[const aIndex: Integer]: T write SetItems; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlRandomAccessInputOutputIterator<T> = interface(IutlRandomAccessIterator) | |||
['{3A8D3C5D-1085-4073-B1D4-DF1886827B6A}'] | |||
function GetItem: T; | |||
function GetItems(const aIndex: Integer): T; | |||
procedure SetItem (const aValue: T); | |||
procedure SetItems(const aIndex: Integer; aValue: T); | |||
property Item: T read GetItem write SetItem; | |||
property Items[const aIndex: Integer]: T read GetItems write SetItems; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function IncIt(aIterator: IutlIterator): Boolean; overload; | |||
function DecIt(aIterator: IutlBidirectionalIterator): Boolean; overload; | |||
function IncIt(aIterator: IutlRandomAccessIterator; const a: Integer): Boolean; overload; | |||
function DecIt(aIterator: IutlRandomAccessIterator; const a: Integer): Boolean; overload; | |||
operator +(aIterator: IutlRandomAccessIterator; const a: Integer): IutlRandomAccessIterator; | |||
operator -(aIterator: IutlRandomAccessIterator; const a: Integer): IutlRandomAccessIterator; | |||
operator < (const i1, i2: TObject): Boolean; inline; | |||
operator > (const i1, i2: TObject): Boolean; inline; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function IncIt(aIterator: IutlIterator): Boolean; | |||
begin | |||
result := aIterator.MoveNext; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function DecIt(aIterator: IutlBidirectionalIterator): Boolean; | |||
begin | |||
result := aIterator.MovePrev; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function IncIt(aIterator: IutlRandomAccessIterator; const a: Integer): Boolean; | |||
begin | |||
result := aIterator.Increment(a); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function DecIt(aIterator: IutlRandomAccessIterator; const a: Integer): Boolean; | |||
begin | |||
result := aIterator.Decrement(a); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator + (aIterator: IutlRandomAccessIterator; const a: Integer): IutlRandomAccessIterator; | |||
begin | |||
result := IutlRandomAccessIterator(aIterator.Clone); | |||
result.Increment(a); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator - (aIterator: IutlRandomAccessIterator; const a: Integer): IutlRandomAccessIterator; | |||
begin | |||
result := IutlRandomAccessIterator(aIterator.Clone); | |||
result.Decrement(a); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator < (const i1, i2: TObject): Boolean; | |||
begin | |||
result := Pointer(i1) < Pointer(i2); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator > (const i1, i2: TObject): Boolean; | |||
begin | |||
result := Pointer(i1) > Pointer(i2); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlEqualityComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
result := (i1 = i2); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlCalbackEqualityComparer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCalbackEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
case fType of | |||
eetNormal: result := fEvent (i1, i2); | |||
eetObject: result := fEventO(i1, i2); | |||
eetNested: result := fEventN(i1, i2); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEvent); | |||
begin | |||
inherited Create; | |||
fType := eetNormal; | |||
fEvent := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEventO); | |||
begin | |||
inherited Create; | |||
fType := eetObject; | |||
fEventO := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEventN); | |||
begin | |||
inherited Create; | |||
fType := eetNested; | |||
fEventN := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlComparer.Compare(constref i1, i2: T): Integer; | |||
begin | |||
if (i1 < i2) then | |||
result := -1 | |||
else if (i1 > i2) then | |||
result := 1 | |||
else | |||
result := 0; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlCallbackComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCallbackComparer.Compare(constref i1, i2: T): Integer; | |||
begin | |||
case fType of | |||
cetNormal: result := fEvent (i1, i2); | |||
cetObject: result := fEventO(i1, i2); | |||
cetNested: result := fEventN(i1, i2); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCallbackComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
result := (Compare(i1, i2) = 0); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCallbackComparer.Create(const aEvent: TCompareEvent); | |||
begin | |||
inherited Create; | |||
fType := cetNormal; | |||
fEvent := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCallbackComparer.Create(const aEvent: TCompareEventO); | |||
begin | |||
inherited Create; | |||
fType := cetObject; | |||
fEventO := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCallbackComparer.Create(const aEvent: TCompareEventN); | |||
begin | |||
inherited Create; | |||
fType := cetNested; | |||
fEventN := aEvent; | |||
end; | |||
end. | |||
@@ -1,297 +0,0 @@ | |||
unit uutlLinkedListTests; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, TestFramework, | |||
uutlGenerics, uutlExceptions; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
TIntList = specialize TutlLinkedList<Integer>; | |||
TutlLinkedListTests = class(TTestCase) | |||
private | |||
fIntList: TIntList; | |||
procedure AccessPropFirst; | |||
procedure AccessPropLast; | |||
protected | |||
procedure SetUp; override; | |||
procedure TearDown; override; | |||
published | |||
procedure Prop_Count; | |||
procedure Prop_IsEmpty; | |||
procedure Prop_First; | |||
procedure Prop_Last; | |||
procedure Meth_PushFirst_PopFirst; | |||
procedure Meth_PushLast_PopLast; | |||
procedure Meth_InsertBefore; | |||
procedure Meth_InsertAfter; | |||
procedure Meth_Remove; | |||
procedure Meth_Clear; | |||
procedure Iterator; | |||
procedure CompleteIteration; | |||
end; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlLinkedListTests/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.AccessPropFirst; | |||
begin | |||
fIntList.First; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.AccessPropLast; | |||
begin | |||
fIntList.Last; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.SetUp; | |||
begin | |||
inherited SetUp; | |||
fIntList := TIntList.Create(true); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.TearDown; | |||
begin | |||
FreeAndNil(fIntList); | |||
inherited TearDown; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Prop_Count; | |||
begin | |||
AssertEquals(0, fIntList.Count); | |||
fIntList.PushFirst(123); | |||
AssertEquals(1, fIntList.Count); | |||
fIntList.PushFirst(234); | |||
AssertEquals(2, fIntList.Count); | |||
fIntList.PopFirst(true); | |||
AssertEquals(1, fIntList.Count); | |||
fIntList.PopFirst(true); | |||
AssertEquals(0, fIntList.Count); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Prop_IsEmpty; | |||
begin | |||
AssertEquals(true, fIntList.IsEmpty); | |||
fIntList.PushFirst(123); | |||
AssertEquals(false, fIntList.IsEmpty); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Prop_First; | |||
begin | |||
AssertException('empty list does not raise exception when accessing First property', EutlInvalidOperation, @AccessPropFirst); | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
AssertEquals(123, fIntList.First); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Prop_Last; | |||
begin | |||
AssertException('empty list does not raise exception when accessing First property', EutlInvalidOperation, @AccessPropLast); | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
AssertEquals(234, fIntList.Last); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Meth_PushFirst_PopFirst; | |||
begin | |||
fIntList.PushFirst(123); | |||
AssertEquals(123, fIntList.First); | |||
fIntList.PushFirst(234); | |||
AssertEquals(234, fIntList.First); | |||
fIntList.PushFirst(345); | |||
AssertEquals(345, fIntList.First); | |||
fIntList.PushFirst(456); | |||
AssertEquals(456, fIntList.First); | |||
AssertEquals(456, fIntList.PopFirst(false)); | |||
AssertEquals(345, fIntList.First); | |||
AssertEquals( 0, fIntList.PopFirst(true)); | |||
AssertEquals(234, fIntList.First); | |||
AssertEquals(234, fIntList.PopFirst(false)); | |||
AssertEquals(123, fIntList.First); | |||
AssertEquals( 0, fIntList.PopFirst(true)); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Meth_PushLast_PopLast; | |||
begin | |||
fIntList.PushLast(123); | |||
AssertEquals(123, fIntList.Last); | |||
fIntList.PushLast(234); | |||
AssertEquals(234, fIntList.Last); | |||
fIntList.PushLast(345); | |||
AssertEquals(345, fIntList.Last); | |||
fIntList.PushLast(456); | |||
AssertEquals(456, fIntList.Last); | |||
AssertEquals(456, fIntList.PopLast(false)); | |||
AssertEquals(345, fIntList.Last); | |||
AssertEquals( 0, fIntList.PopLast(true)); | |||
AssertEquals(234, fIntList.Last); | |||
AssertEquals(234, fIntList.PopLast(false)); | |||
AssertEquals(123, fIntList.Last); | |||
AssertEquals( 0, fIntList.PopLast(true)); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Meth_InsertBefore; | |||
var | |||
it: TIntList.Iterator; | |||
begin | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
fIntList.PushLast(345); | |||
fIntList.PushLast(456); | |||
it := fIntList.FirstIterator; | |||
fIntList.InsertBefore(it, 999); | |||
AssertTrue(it.MovePrev); | |||
AssertEquals(999, it.Item); | |||
AssertEquals(5, fIntList.Count); | |||
it := fIntList.LastIterator; | |||
fIntList.InsertBefore(it, 888); | |||
AssertTrue(it.MovePrev); | |||
AssertEquals(888, it.Item); | |||
AssertEquals(6, fIntList.Count); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Meth_InsertAfter; | |||
var | |||
it: TIntList.Iterator; | |||
begin | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
fIntList.PushLast(345); | |||
fIntList.PushLast(456); | |||
it := fIntList.FirstIterator; | |||
fIntList.InsertAfter(it, 999); | |||
AssertTrue(it.MoveNext); | |||
AssertEquals(999, it.Item); | |||
AssertEquals(5, fIntList.Count); | |||
it := fIntList.LastIterator; | |||
fIntList.InsertAfter(it, 888); | |||
AssertTrue(it.MoveNext); | |||
AssertEquals(888, it.Item); | |||
AssertEquals(6, fIntList.Count); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Meth_Remove; | |||
var | |||
it: TIntList.Iterator; | |||
begin | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
fIntList.PushLast(345); | |||
fIntList.PushLast(456); | |||
it := fIntList.FirstIterator; | |||
it.MoveNext; | |||
fIntList.Remove(it); | |||
AssertEquals(3, fIntList.Count); | |||
AssertEquals(123, fIntList.First); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Meth_Clear; | |||
begin | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
fIntList.PushLast(345); | |||
fIntList.PushLast(456); | |||
AssertEquals(4, fIntList.Count); | |||
fIntList.Clear; | |||
AssertEquals(0, fIntList.Count); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.Iterator; | |||
var | |||
it1: TIntList.Iterator; | |||
begin | |||
fIntList.PushLast(123); | |||
fIntList.PushLast(234); | |||
fIntList.PushLast(345); | |||
fIntList.PushLast(456); | |||
it1 := fIntList.FirstIterator; | |||
AssertEquals(123, it1.Item); | |||
AssertTrue (it1.IsValid); | |||
AssertTrue (it1.Equals(fIntList.FirstIterator)); | |||
AssertTrue (it1.MoveNext); | |||
AssertEquals(234, it1.Item); | |||
AssertTrue (it1.MoveNext); | |||
AssertEquals(345, it1.Item); | |||
AssertTrue (it1.MoveNext); | |||
AssertEquals(456, it1.Item); | |||
AssertTrue (it1.Equals(fIntList.LastIterator)); | |||
AssertFalse (it1.MoveNext); | |||
fIntList.PopLast; | |||
AssertFalse (it1.IsValid); | |||
it1 := fIntList.LastIterator; | |||
AssertEquals(345, it1.Item); | |||
AssertTrue (it1.IsValid); | |||
AssertTrue (it1.Equals(fIntList.LastIterator)); | |||
AssertTrue (it1.MovePrev); | |||
AssertEquals(234, it1.Item); | |||
AssertTrue (it1.MovePrev); | |||
AssertEquals(123, it1.Item); | |||
AssertTrue (it1.Equals(fIntList.FirstIterator)); | |||
AssertFalse (it1.MovePrev); | |||
fIntList.PopFirst; | |||
AssertFalse (it1.IsValid); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlLinkedListTests.CompleteIteration; | |||
var | |||
i: Integer; | |||
it, itEnd: TIntList.Iterator; | |||
begin | |||
for i := 0 to 10 do | |||
fIntList.PushLast(i); | |||
i := 0; | |||
it := fIntList.FirstIterator; | |||
itEnd := fIntList.LastIterator; | |||
AssertTrue(itEnd.MovePrev); | |||
repeat | |||
AssertEquals(i, it.Item); | |||
inc(i); | |||
until not it.MoveNext or it.Equals(itEnd); | |||
AssertTrue(it.MoveNext); | |||
AssertEquals(10, it.Item); | |||
end; | |||
initialization | |||
RegisterTest(TutlLinkedListTests.Suite); | |||
end. | |||
@@ -9,6 +9,7 @@ uses | |||
uTestHelper, uutlGenerics; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
TIntMap = specialize TutlMap<Integer, Integer>; | |||
TObjMap = specialize TutlMap<TIntfObj, TIntfObj>; | |||
TutlMapTests = class(TIntfObjOwner) | |||
@@ -48,6 +49,9 @@ type | |||
implementation | |||
uses | |||
uutlExceptions; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlMapTests////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -217,7 +221,7 @@ end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlMapTests.Prop_AutoCreate; | |||
begin | |||
AssertException('autocreate false does not throw exception', EutlMap, @AssignNonExistsingItem); | |||
AssertException('autocreate false does not throw exception', EutlInvalidOperation, @AssignNonExistsingItem); | |||
fIntMap.AutoCreate := true; | |||
AssignNonExistsingItem; | |||
end; | |||
@@ -10,14 +10,14 @@ uses | |||
type | |||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlBinarySearch<T> = class(TObject) | |||
generic TutlBinarySearch<T> = class | |||
public type | |||
IReadOnlyIndexer = specialize IutlReadOnlyIndexer<T>; | |||
IComparer = specialize IutlComparer<T>; | |||
IReadOnlyArray = specialize IutlReadOnlyArray<T>; | |||
IComparer = specialize IutlComparer<T>; | |||
private | |||
class function DoSearch( | |||
constref aIndexer: IReadOnlyIndexer; | |||
constref aArray: IReadOnlyArray; | |||
constref aComparer: IComparer; | |||
const aMin: Integer; | |||
const aMax: Integer; | |||
@@ -25,38 +25,43 @@ type | |||
out aIndex: Integer): Boolean; | |||
public | |||
// search aItem in aIndexer using aComparer | |||
// search aItem in aList using aComparer | |||
// aList needs to bee sorted | |||
// aIndex is the index the item was found or should be inserted | |||
// returns TRUE when found, FALSE otherwise | |||
class function Search( | |||
constref aIndexer: IReadOnlyIndexer; | |||
constref aArray: IReadOnlyArray; | |||
constref aComparer: IComparer; | |||
constref aItem: T; | |||
out aIndex: Integer): Boolean; | |||
end; | |||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function Supports(const aInstance: TObject; const aClass: TClass; out aObj): Boolean; overload; | |||
generic TutlQuickSort<T> = class | |||
public type | |||
IArray = specialize IutlArray<T>; | |||
IComparer = specialize IutlComparer<T>; | |||
implementation | |||
private | |||
class procedure DoSort( | |||
constref aArray: IArray; | |||
constref aComparer: IComparer; | |||
aLow: Integer; | |||
aHigh: Integer); | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function Supports(const aInstance: TObject; const aClass: TClass; out aObj): Boolean; | |||
begin | |||
result := Assigned(aInstance) and aInstance.InheritsFrom(aClass); | |||
if result then | |||
TObject(aObj) := aInstance | |||
else | |||
TObject(aObj) := nil; | |||
end; | |||
public | |||
class procedure Sort( | |||
constref aArray: IArray; | |||
constref aComparer: IComparer); | |||
end; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlBinarySearch////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class function TutlBinarySearch.DoSearch( | |||
constref aIndexer: IReadOnlyIndexer; | |||
constref aArray: IReadOnlyArray; | |||
constref aComparer: IComparer; | |||
const aMin: Integer; | |||
const aMax: Integer; | |||
@@ -67,14 +72,14 @@ var | |||
begin | |||
if (aMin <= aMax) then begin | |||
i := aMin + Trunc((aMax - aMin) / 2); | |||
cmp := aComparer.Compare(aItem, aIndexer.Items[i]); | |||
cmp := aComparer.Compare(aItem, aArray[i]); | |||
if (cmp = 0) then begin | |||
result := true; | |||
aIndex := i; | |||
end else if (cmp < 0) then | |||
result := DoSearch(aIndexer, aComparer, aMin, i-1, aItem, aIndex) | |||
result := DoSearch(aArray, aComparer, aMin, i-1, aItem, aIndex) | |||
else if (cmp > 0) then | |||
result := DoSearch(aIndexer, aComparer, i+1, aMax, aItem, aIndex); | |||
result := DoSearch(aArray, aComparer, i+1, aMax, aItem, aIndex); | |||
end else begin | |||
result := false; | |||
aIndex := aMin; | |||
@@ -83,12 +88,62 @@ end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class function TutlBinarySearch.Search( | |||
constref aIndexer: IReadOnlyIndexer; | |||
constref aArray: IReadOnlyArray; | |||
constref aComparer: IComparer; | |||
constref aItem: T; | |||
out aIndex: Integer): Boolean; | |||
begin | |||
result := DoSearch(aIndexer, aComparer, 0, aIndexer.Count-1, aItem, aIndex); | |||
result := DoSearch(aArray, aComparer, 0, aArray.Count-1, aItem, aIndex); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlQuickSort///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class procedure TutlQuickSort.DoSort( | |||
constref aArray: IArray; | |||
constref aComparer: IComparer; | |||
aLow: Integer; | |||
aHigh: Integer); | |||
var | |||
lo, hi: Integer; | |||
p, tmp: T; | |||
begin | |||
repeat | |||
lo := aLow; | |||
hi := aHigh; | |||
p := aArray[(aLow + aHigh) div 2]; | |||
repeat | |||
while (aComparer.Compare(p, aArray[lo]) > 0) do | |||
lo := lo + 1; | |||
while (aComparer.Compare(p, aArray[hi]) < 0) do | |||
hi := hi - 1; | |||
if (lo <= hi) then begin | |||
tmp := aArray[lo]; | |||
aArray[lo] := aArray[hi]; | |||
aArray[hi] := tmp; | |||
lo := lo + 1; | |||
hi := hi - 1; | |||
end; | |||
until (lo > hi); | |||
if (hi - aLow < aHigh - lo) then begin | |||
if (aLow < hi) then | |||
DoSort(aArray, aComparer, aLow, hi); | |||
aLow := lo; | |||
end else begin | |||
if (lo < aHigh) then | |||
DoSort(aArray, aComparer, lo, aHigh); | |||
aHigh := hi; | |||
end; | |||
until (aLow >= aHigh); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
class procedure TutlQuickSort.Sort( | |||
constref aArray: IArray; | |||
constref aComparer: IComparer); | |||
begin | |||
DoSort(aArray, aComparer, 0, aArray.GetCount-1); | |||
end; | |||
end. | |||
@@ -0,0 +1,138 @@ | |||
unit uutlArrayContainer; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, | |||
uutlCommon; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlArrayContainer<T> = class(TutlInterfaceNoRefCount) | |||
protected type | |||
PT = ^T; | |||
strict private | |||
fList: PT; | |||
fCapacity: Integer; | |||
fOwnsItems: Boolean; | |||
fCanShrink: Boolean; | |||
fCanExpand: Boolean; | |||
function GetIsEmpty: Boolean; inline; | |||
protected | |||
function GetCount: Integer; virtual; abstract; | |||
procedure SetCount (const aValue: Integer); virtual; abstract; | |||
function GetInternalItem (const aIndex: Integer): PT; | |||
procedure SetCapacity (const aValue: integer); virtual; | |||
procedure Release (var aItem: T; const aFreeItem: Boolean); virtual; | |||
procedure Shrink (const aExactFit: Boolean); | |||
procedure Expand; | |||
protected | |||
property Count: Integer read GetCount write SetCount; | |||
property IsEmpty: Boolean read GetIsEmpty; | |||
property Capacity: Integer read fCapacity write SetCapacity; | |||
property CanShrink: Boolean read fCanShrink write fCanShrink; | |||
property CanExpand: Boolean read fCanExpand write fCanExpand; | |||
property OwnsItems: Boolean read fOwnsItems write fOwnsItems; | |||
public | |||
constructor Create(const aOwnsItems: Boolean); | |||
destructor Destroy; override; | |||
end; | |||
implementation | |||
uses | |||
uutlExceptions; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlArrayContainer//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayContainer.GetIsEmpty: Boolean; | |||
begin | |||
result := (Count = 0); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayContainer.GetInternalItem(const aIndex: Integer): PT; | |||
begin | |||
if (aIndex < 0) or (aIndex >= fCapacity) then | |||
raise EutlOutOfRange.Create('capacity out of range', aIndex, 0, fCapacity-1); | |||
result := fList + aIndex; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayContainer.SetCapacity(const aValue: integer); | |||
begin | |||
if (fCapacity = aValue) then | |||
exit; | |||
if (aValue < Count) then | |||
raise EutlArgument.Create('can not reduce capacity below count', 'Capacity'); | |||
ReAllocMem(fList, aValue * SizeOf(T)); | |||
FillByte((fList + fCapacity)^, (aValue - fCapacity) * SizeOf(T), 0); | |||
fCapacity := aValue; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayContainer.Release(var aItem: T; const aFreeItem: Boolean); | |||
begin | |||
utlFinalizeObject(aItem, TypeInfo(aItem), fOwnsItems and aFreeItem); | |||
FillByte(aItem, SizeOf(aItem), 0); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayContainer.Shrink(const aExactFit: Boolean); | |||
begin | |||
if not fCanShrink then | |||
raise EutlInvalidOperation.Create('shrinking is not allowed'); | |||
if (aExactFit) then | |||
SetCapacity(Count) | |||
else if (fCapacity > 128) and (Count < fCapacity shr 2) then // less than 25% used | |||
SetCapacity(fCapacity shr 1); // shrink to 50% | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayContainer.Expand; | |||
begin | |||
if (Count < fCapacity) then | |||
exit; | |||
if not fCanExpand then | |||
raise EutlInvalidOperation.Create('expanding is not allowed'); | |||
if (fCapacity <= 0) then | |||
SetCapacity(4) | |||
else if (fCapacity < 128) then | |||
SetCapacity(fCapacity shl 1) // + 100% | |||
else | |||
SetCapacity(fCapacity + fCapacity shr 2); // + 25% | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlArrayContainer.Create(const aOwnsItems: Boolean); | |||
begin | |||
inherited Create; | |||
fOwnsItems := aOwnsItems; | |||
fList := nil; | |||
fCapacity := 0; | |||
fCanExpand := true; | |||
fCanShrink := true; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
destructor TutlArrayContainer.Destroy; | |||
begin | |||
if Assigned(fList) then begin | |||
FreeMem(fList); | |||
fList := nil; | |||
end; | |||
inherited Destroy; | |||
end; | |||
end. | |||
@@ -5,7 +5,7 @@ unit uutlCommon; | |||
interface | |||
uses | |||
Classes, SysUtils; | |||
Classes, SysUtils, typinfo; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -22,8 +22,46 @@ type | |||
property RefCount: LongInt read fRefCount; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure utlFinalizeObject(var obj; const aTypeInfo: PTypeInfo; const aFreeObject: Boolean); | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Helper Methods//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure utlFinalizeObject(var obj; const aTypeInfo: PTypeInfo; const aFreeObject: Boolean); | |||
var | |||
o: TObject; | |||
begin | |||
case aTypeInfo^.Kind of | |||
tkClass: begin | |||
if (aFreeObject) then begin | |||
o := TObject(obj); | |||
Pointer(obj) := nil; | |||
if Assigned(o) then | |||
o.Free; | |||
end; | |||
end; | |||
tkInterface: begin | |||
IUnknown(obj) := nil; | |||
end; | |||
tkAString: begin | |||
AnsiString(Obj) := ''; | |||
end; | |||
tkUString: begin | |||
UnicodeString(Obj) := ''; | |||
end; | |||
tkString: begin | |||
String(Obj) := ''; | |||
end; | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlInterfaceNoRefCount/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
@@ -0,0 +1,224 @@ | |||
unit uutlComparer; | |||
{$mode objfpc}{$H+} | |||
{$modeswitch nestedprocvars} | |||
interface | |||
uses | |||
Classes, SysUtils, | |||
uutlInterfaces; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlEqualityComparer<T> = class( | |||
TInterfacedObject, | |||
specialize IutlEqualityComparer<T>) | |||
public | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlEqualityCompareEvent<T> = function(constref i1, i2: T): Boolean; | |||
generic TutlEqualityCompareEventO<T> = function(constref i1, i2: T): Boolean of object; | |||
generic TutlEqualityCompareEventN<T> = function(constref i1, i2: T): Boolean is nested; | |||
generic TutlCalbackEqualityComparer<T> = class( | |||
TInterfacedObject, | |||
specialize IutlEqualityComparer<T>) | |||
private type | |||
TEqualityCompareEventType = (eetNormal, eetObject, eetNested); | |||
public type | |||
TCompareEvent = specialize TutlEqualityCompareEvent<T>; | |||
TCompareEventO = specialize TutlEqualityCompareEventO<T>; | |||
TCompareEventN = specialize TutlEqualityCompareEventN<T>; | |||
strict private | |||
fType: TEqualityCompareEventType; | |||
fEvent: TCompareEvent; | |||
fEventO: TCompareEventO; | |||
fEventN: TCompareEventN; | |||
public | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
constructor Create(const aEvent: TCompareEvent); overload; | |||
constructor Create(const aEvent: TCompareEventO); overload; | |||
constructor Create(const aEvent: TCompareEventN); overload; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlComparer<T> = class( | |||
specialize TutlEqualityComparer<T>, | |||
specialize IutlEqualityComparer<T>, | |||
specialize IutlComparer<T>) | |||
public | |||
function Compare(constref i1, i2: T): Integer; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlCompareEvent<T> = function(constref i1, i2: T): Integer; | |||
generic TutlCompareEventO<T> = function(constref i1, i2: T): Integer of object; | |||
generic TutlCompareEventN<T> = function(constref i1, i2: T): Integer is nested; | |||
generic TutlCallbackComparer<T> = class( | |||
TInterfacedObject, | |||
specialize IutlEqualityComparer<T>, | |||
specialize IutlComparer<T>) | |||
private type | |||
TCompareEventType = (cetNormal, cetObject, cetNested); | |||
public type | |||
TCompareEvent = specialize TutlCompareEvent<T>; | |||
TCompareEventO = specialize TutlCompareEventO<T>; | |||
TCompareEventN = specialize TutlCompareEventN<T>; | |||
strict private | |||
fType: TCompareEventType; | |||
fEvent: TCompareEvent; | |||
fEventO: TCompareEventO; | |||
fEventN: TCompareEventN; | |||
public | |||
function Compare(constref i1, i2: T): Integer; | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
constructor Create(const aEvent: TCompareEvent); overload; | |||
constructor Create(const aEvent: TCompareEventO); overload; | |||
constructor Create(const aEvent: TCompareEventN); overload; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator <(const i1, i2: TObject): Boolean; inline; | |||
operator >(const i1, i2: TObject): Boolean; inline; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator <(const i1, i2: TObject): Boolean; inline; | |||
begin | |||
result := Pointer(i1) < Pointer(i2); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator >(const i1, i2: TObject): Boolean; inline; | |||
begin | |||
result := Pointer(i1) > Pointer(i2); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlEqualityComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
result := (i1 = i2); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlCalbackEqualityComparer/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCalbackEqualityComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
result := false; | |||
case fType of | |||
eetNormal: result := fEvent (i1, i2); | |||
eetObject: result := fEventO(i1, i2); | |||
eetNested: result := fEventN(i1, i2); | |||
else | |||
raise Exception.Create('invalid or unknown callback type'); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEvent); | |||
begin | |||
inherited Create; | |||
fType := eetNormal; | |||
fEvent := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEventO); | |||
begin | |||
inherited Create; | |||
fType := eetObject; | |||
fEventO := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackEqualityComparer.Create(const aEvent: TCompareEventN); | |||
begin | |||
inherited Create; | |||
fType := eetNested; | |||
fEventN := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlComparer.Compare(constref i1, i2: T): Integer; | |||
begin | |||
if (i1 < i2) then | |||
result := -1 | |||
else if (i1 > i2) then | |||
result := 1 | |||
else | |||
result := 0; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlCallbackComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCallbackComparer.Compare(constref i1, i2: T): Integer; | |||
begin | |||
result := 0; | |||
case fType of | |||
cetNormal: result := fEvent (i1, i2); | |||
cetObject: result := fEventO(i1, i2); | |||
cetNested: result := fEventN(i1, i2); | |||
else | |||
raise Exception.Create('invalid or unknown callback type'); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCallbackComparer.EqualityCompare(constref i1, i2: T): Boolean; | |||
begin | |||
result := (Compare(i1, i2) = 0); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCallbackComparer.Create(const aEvent: TCompareEvent); | |||
begin | |||
inherited Create; | |||
fType := cetNormal; | |||
fEvent := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCallbackComparer.Create(const aEvent: TCompareEventO); | |||
begin | |||
inherited Create; | |||
fType := cetObject; | |||
fEventO := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCallbackComparer.Create(const aEvent: TCompareEventN); | |||
begin | |||
inherited Create; | |||
fType := cetNested; | |||
fEventN := aEvent; | |||
end; | |||
end. | |||
@@ -0,0 +1,515 @@ | |||
unit uutlEnumerator; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, | |||
uutlInterfaces; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlEnumerator<T> = class( | |||
TInterfacedObject, | |||
specialize IutlEnumerator<T>) | |||
public type | |||
IEnumerator = specialize IutlEnumerator<T>; | |||
IFilter = specialize IutlFilter<T>; | |||
TArray = specialize TGenericArray<T>; | |||
public { IEnumerator } | |||
function GetCurrent: T; virtual; abstract; | |||
function MoveNext: Boolean; virtual; abstract; | |||
procedure Reset; virtual; abstract; | |||
public { IutlEnumerator } | |||
function GetEnumerator: IEnumerator; virtual; | |||
function Count: Integer; virtual; | |||
function Reverse: IEnumerator; virtual; | |||
function Skip (const aCount: Integer): IEnumerator; virtual; | |||
function Take (const aCount: Integer): IEnumerator; virtual; | |||
function Where(const aFilter: IFilter): IEnumerator; virtual; | |||
function ToArray: TArray; virtual; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlMemoryEnumerator<T> = class( | |||
specialize TutlEnumerator<T>) | |||
public type | |||
PT = ^T; | |||
strict private | |||
fReverse: Boolean; | |||
fMemory: PT; | |||
fCurrent: Integer; | |||
fCount: Integer; | |||
public { IEnumerator } | |||
function GetCurrent: T; override; | |||
function MoveNext: Boolean; override; | |||
procedure Reset; override; | |||
public { IutlEnumerator } | |||
function Count: Integer; override; | |||
function Reverse: IEnumerator; override; | |||
public | |||
constructor Create(const aMemory: PT; const aCount: Integer); overload; | |||
constructor Create(const aMemory: PT; const aCount: Integer; const aReverse: Boolean); overload; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlArrayEnumerator<T> = class( | |||
specialize TutlEnumerator<T>) | |||
strict private | |||
fArray: TArray; | |||
fReverse: Boolean; | |||
fCurrent: Integer; | |||
fFirst: Integer; | |||
fLast: Integer; | |||
public { IEnumerator } | |||
function GetCurrent: T; override; | |||
function MoveNext: Boolean; override; | |||
procedure Reset; override; | |||
public { IutlEnumerator } | |||
function Count: Integer; override; | |||
function Reverse: IEnumerator; override; | |||
function Skip(const aCount: Integer): IEnumerator; override; | |||
function Take(const aCount: Integer): IEnumerator; override; | |||
function ToArray: TArray; override; | |||
public | |||
constructor Create( | |||
const aArray: TArray); overload; | |||
constructor Create( | |||
const aArray: TArray; | |||
const aReverse: Boolean; | |||
const aFirst: Integer; | |||
const aLast: Integer); overload; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlSkipTakeEnumerator<T> = class( | |||
specialize TutlEnumerator<T>) | |||
strict private | |||
fEnumerator: IEnumerator; | |||
fSkip: Integer; // greater than 0: skip X; lower than 0: skip none | |||
fTake: Integer; // greater than 0: take X; lower than 0: take all | |||
fCurrentSkip: Integer; | |||
fCurrentTake: Integer; | |||
public { IEnumerator } | |||
function GetCurrent: T; override; | |||
function MoveNext: Boolean; override; | |||
procedure Reset; override; | |||
public | |||
constructor Create(const aEnumerator: IEnumerator; const aSkip: Integer; const aTake: Integer); | |||
destructor Destroy; override; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlWhereEnumerator<T> = class( | |||
specialize TutlEnumerator<T>) | |||
strict private | |||
fEnumerator: IEnumerator; | |||
fFilter: IFilter; | |||
public { IEnumerator } | |||
function GetCurrent: T; override; | |||
function MoveNext: Boolean; override; | |||
procedure Reset; override; | |||
public | |||
constructor Create(const aEnumerator: IEnumerator; const aFilter: IFilter); | |||
destructor Destroy; override; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlSelectEnumerator<Tin, Tout> = class( | |||
specialize TutlEnumerator<Tout>) | |||
public type | |||
IInEnumerator = specialize IutlEnumerator<Tin>; | |||
ISelector = specialize IutlSelector<Tin, Tout>; | |||
strict private | |||
fEnumerator: IInEnumerator; | |||
fSelector: ISelector; | |||
public { IEnumerator } | |||
function GetCurrent: Tout; override; | |||
function MoveNext: Boolean; override; | |||
procedure Reset; override; | |||
public | |||
constructor Create(const aEnumerator: IInEnumerator; const aSelector: ISelector); | |||
destructor Destroy; override; | |||
end; | |||
implementation | |||
uses | |||
uutlExceptions; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.GetEnumerator: IEnumerator; | |||
begin | |||
result := self; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.Reverse: IEnumerator; | |||
var | |||
arr: TArray; | |||
begin | |||
arr := ToArray; | |||
result := specialize TutlArrayEnumerator<T>.Create(arr, true, low(arr), high(arr)); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.Skip(const aCount: Integer): IEnumerator; | |||
begin | |||
result := specialize TutlSkipTakeEnumerator<T>.Create(self, aCount, -1); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.Take(const aCount: Integer): IEnumerator; | |||
begin | |||
result := specialize TutlSkipTakeEnumerator<T>.Create(self, -1, aCount); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.Where(const aFilter: IFilter): IEnumerator; | |||
begin | |||
result := specialize TutlWhereEnumerator<T>.Create(self, aFilter); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.ToArray: TArray; | |||
var | |||
i: Integer; | |||
arr: array of T; | |||
begin | |||
i := 0; | |||
SetLength(arr, i); | |||
Reset; | |||
while MoveNext do begin | |||
inc(i); | |||
SetLength(arr, i); | |||
arr[i-1] := GetCurrent; | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEnumerator.Count: Integer; | |||
begin | |||
result := 0; | |||
Reset; | |||
while MoveNext do | |||
inc(result); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlMemoryEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlMemoryEnumerator.GetCurrent: T; | |||
var | |||
p: PT; | |||
begin | |||
if (fCurrent < 0) or (fCurrent >= fCount) then | |||
raise EutlInvalidOperation.Create('enumerator is not initialized'); | |||
p := fMemory; | |||
if fReverse | |||
then inc(p, fCount - fCurrent - 1) | |||
else inc(p, fCurrent); | |||
result := p^; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlMemoryEnumerator.MoveNext: Boolean; | |||
begin | |||
inc(fCurrent); | |||
result := (fCurrent < fCount); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlMemoryEnumerator.Reset; | |||
begin | |||
fCurrent := -1; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlMemoryEnumerator.Count: Integer; | |||
begin | |||
result := fCount; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlMemoryEnumerator.Reverse: IEnumerator; | |||
begin | |||
result := TutlMemoryEnumerator.Create(fMemory, fCount, not fReverse); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlMemoryEnumerator.Create(const aMemory: PT; const aCount: Integer); | |||
begin | |||
Create(aMemory, aCount, false); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlMemoryEnumerator.Create(const aMemory: PT; const aCount: Integer; const aReverse: Boolean); | |||
begin | |||
inherited Create; | |||
fMemory := aMemory; | |||
fCount := aCount; | |||
fReverse := aReverse; | |||
fCurrent := -1; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlArrayEnumerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.GetCurrent: T; | |||
begin | |||
if (fCurrent < fFirst) or (fCurrent > fLast) then | |||
raise EutlInvalidOperation.Create('enumerator is not initialized'); | |||
result := fArray[fCurrent]; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.MoveNext: Boolean; | |||
begin | |||
if fReverse | |||
then dec(fCurrent) | |||
else inc(fCurrent); | |||
result := (fFirst <= fCurrent) and (fCurrent <= fLast); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlArrayEnumerator.Reset; | |||
begin | |||
if fReverse | |||
then fCurrent := fLast + 1 | |||
else fCurrent := fFirst - 1; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.Count: Integer; | |||
begin | |||
result := fLast - fFirst + 1; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.Reverse: IEnumerator; | |||
begin | |||
result := specialize TutlArrayEnumerator<T>.Create(fArray, not fReverse, fFirst, fLast); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.Skip(const aCount: Integer): IEnumerator; | |||
begin | |||
if fReverse | |||
then result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fFirst, fLast - aCount) | |||
else result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fFirst + aCount, fLast); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.Take(const aCount: Integer): IEnumerator; | |||
begin | |||
if fReverse | |||
then result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fLast - aCount + 1, fLast) | |||
else result := specialize TutlArrayEnumerator<T>.Create(fArray, fReverse, fFirst, fFirst + aCount - 1); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlArrayEnumerator.ToArray: TArray; | |||
var | |||
i: Integer; | |||
begin | |||
SetLength(result, fLast - fFirst + 1); | |||
if fReverse then begin | |||
for i := fFirst to fLast do | |||
result[i-fFirst] := fArray[i]; | |||
end else | |||
System.Move(fArray[fFirst], result[0], Length(result)); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlArrayEnumerator.Create(const aArray: TArray); | |||
begin | |||
Create(aArray, false, low(aArray), high(aArray)); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlArrayEnumerator.Create( | |||
const aArray: TArray; | |||
const aReverse: Boolean; | |||
const aFirst: Integer; | |||
const aLast: Integer); | |||
begin | |||
inherited Create; | |||
fArray := aArray; | |||
fReverse := aReverse; | |||
fFirst := aFirst; | |||
fLast := aLast; | |||
if (fFirst < low(fArray)) then | |||
fFirst := low(fArray); | |||
if (fLast > high(fArray)) then | |||
fLast := high(fArray); | |||
if fReverse | |||
then fCurrent := fLast + 1 | |||
else fCurrent := fFirst - 1; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlSkipTakeEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlSkipTakeEnumerator.GetCurrent: T; | |||
begin | |||
result := fEnumerator.Current; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlSkipTakeEnumerator.MoveNext: Boolean; | |||
begin | |||
while (fCurrentSkip > 0) and fEnumerator.MoveNext do | |||
dec(fCurrentSkip); | |||
result := | |||
(fCurrentSkip <= 0) | |||
and (fCurrentTake <> 0) | |||
and fEnumerator.MoveNext; | |||
if (fCurrentTake > 0) then | |||
dec(fCurrentTake); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlSkipTakeEnumerator.Reset; | |||
begin | |||
fEnumerator.Reset; | |||
fCurrentSkip := fSkip; | |||
fCurrentTake := fTake; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlSkipTakeEnumerator.Create(const aEnumerator: IEnumerator; const aSkip: Integer; const aTake: Integer); | |||
begin | |||
if not Assigned(aEnumerator) then | |||
raise EutlArgumentNil.Create('aEnumerator'); | |||
inherited Create; | |||
fEnumerator := aEnumerator; | |||
fSkip := aSkip; | |||
fTake := aTake; | |||
fCurrentSkip := aSkip; | |||
fCurrentTake := aTake; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
destructor TutlSkipTakeEnumerator.Destroy; | |||
begin | |||
fEnumerator := nil; | |||
inherited Destroy; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlWhereEnumerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlWhereEnumerator.GetCurrent: T; | |||
begin | |||
result := fEnumerator.Current; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlWhereEnumerator.MoveNext: Boolean; | |||
begin | |||
repeat | |||
result := fEnumerator.MoveNext; | |||
until not result or fFilter.Filter(fEnumerator.Current); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlWhereEnumerator.Reset; | |||
begin | |||
fEnumerator.Reset; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlWhereEnumerator.Create(const aEnumerator: IEnumerator; const aFilter: IFilter); | |||
begin | |||
if not Assigned(aEnumerator) then | |||
raise EutlArgumentNil.Create('aEnumerator'); | |||
if not Assigned(aFilter) then | |||
raise EutlArgumentNil.Create('aFilter'); | |||
inherited Create; | |||
fEnumerator := aEnumerator; | |||
fFilter := aFilter; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
destructor TutlWhereEnumerator.Destroy; | |||
begin | |||
fEnumerator := nil; | |||
fFilter := nil; | |||
inherited Destroy; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlSelectEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlSelectEnumerator.GetCurrent: Tout; | |||
begin | |||
result := fSelector.Select(fEnumerator.Current); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlSelectEnumerator.MoveNext: Boolean; | |||
begin | |||
result := fEnumerator.MoveNext; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlSelectEnumerator.Reset; | |||
begin | |||
fEnumerator.Reset; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlSelectEnumerator.Create(const aEnumerator: IInEnumerator; const aSelector: ISelector); | |||
begin | |||
if not Assigned(aEnumerator) then | |||
raise EutlArgumentNil.Create('aEnumerator'); | |||
if not Assigned(aSelector) then | |||
raise EutlArgumentNil.Create('aSelector'); | |||
inherited Create; | |||
fEnumerator := aEnumerator; | |||
fSelector := aSelector; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
destructor TutlSelectEnumerator.Destroy; | |||
begin | |||
fEnumerator := nil; | |||
fSelector := nil; | |||
inherited Destroy; | |||
end; | |||
end. | |||
@@ -14,6 +14,9 @@ type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
EutlInvalidOperation = class(Exception); | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
EutlNotSupported = class(Exception); | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
EutlOutOfRange = class(EutlException) | |||
private | |||
@@ -0,0 +1,157 @@ | |||
unit uutlFilter; | |||
{$mode objfpc}{$H+} | |||
{$modeswitch nestedprocvars} | |||
interface | |||
uses | |||
Classes, SysUtils, | |||
uutlInterfaces; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlFilterEvent<T> = function(constref i: T): Boolean; | |||
generic TutlFilterEventO<T> = function(constref i: T): Boolean of object; | |||
generic TutlFilterEventN<T> = function(constref i: T): Boolean is nested; | |||
generic TutlCalbackFilter<T> = class( | |||
TInterfacedObject, | |||
specialize IutlFilter<T>) | |||
private type | |||
TFilterEventType = (fetNormal, fetObject, fetNested); | |||
public type | |||
TFilterEvent = specialize TutlFilterEvent<T>; | |||
TFilterEventO = specialize TutlFilterEventO<T>; | |||
TFilterEventN = specialize TutlFilterEventN<T>; | |||
strict private | |||
fType: TFilterEventType; | |||
fEvent: TFilterEvent; | |||
fEventO: TFilterEventO; | |||
fEventN: TFilterEventN; | |||
public | |||
function Filter(constref i: T): Boolean; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
constructor Create(const aEvent: TFilterEvent); overload; | |||
constructor Create(const aEvent: TFilterEventO); overload; | |||
constructor Create(const aEvent: TFilterEventN); overload; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlSelectEvent <Tin, Tout> = function(constref i: Tin): Tout; | |||
generic TutlSelectEventO<Tin, Tout> = function(constref i: Tin): Tout of object; | |||
generic TutlSelectEventN<Tin, Tout> = function(constref i: Tin): Tout is nested; | |||
generic TutlCalbackSelector<Tin, Tout> = class( | |||
TInterfacedObject, | |||
specialize IutlSelector<Tin, Tout>) | |||
private type | |||
TSelectEventType = (setNormal, setObject, setNested); | |||
public type | |||
TSelectEvent = specialize TutlSelectEvent <Tin, Tout>; | |||
TSelectEventO = specialize TutlSelectEventO<Tin, Tout>; | |||
TSelectEventN = specialize TutlSelectEventN<Tin, Tout>; | |||
strict private | |||
fType: TSelectEventType; | |||
fEvent: TSelectEvent; | |||
fEventO: TSelectEventO; | |||
fEventN: TSelectEventN; | |||
public | |||
function Select(constref i: Tin): Tout; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
constructor Create(const aEvent: TSelectEvent); overload; | |||
constructor Create(const aEvent: TSelectEventO); overload; | |||
constructor Create(const aEvent: TSelectEventN); overload; | |||
end; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlCalbackFilter///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCalbackFilter.Filter(constref i: T): Boolean; | |||
begin | |||
result := false; | |||
case fType of | |||
fetNormal: result := fEvent (i); | |||
fetObject: result := fEventO(i); | |||
fetNested: result := fEventN(i); | |||
else | |||
raise Exception.Create('invalid or unknown callback type'); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackFilter.Create(const aEvent: TFilterEvent); | |||
begin | |||
inherited Create; | |||
fType := fetNormal; | |||
fEvent := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackFilter.Create(const aEvent: TFilterEventO); | |||
begin | |||
inherited Create; | |||
fType := fetObject; | |||
fEventO := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackFilter.Create(const aEvent: TFilterEventN); | |||
begin | |||
inherited Create; | |||
fType := fetNested; | |||
fEventN := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlCalbackSelector/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlCalbackSelector.Select(constref i: Tin): Tout; | |||
begin | |||
case fType of | |||
setNormal: result := fEvent (i); | |||
setObject: result := fEventO(i); | |||
setNested: result := fEventN(i); | |||
else | |||
raise Exception.Create('invalid or unknown callback type'); | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackSelector.Create(const aEvent: TSelectEvent); | |||
begin | |||
inherited Create; | |||
fType := setNormal; | |||
fEvent := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackSelector.Create(const aEvent: TSelectEventO); | |||
begin | |||
inherited Create; | |||
fType := setObject; | |||
fEventO := aEvent; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlCalbackSelector.Create(const aEvent: TSelectEventN); | |||
begin | |||
inherited Create; | |||
fType := setNested; | |||
fEventN := aEvent; | |||
end; | |||
end. | |||
@@ -1,7 +1,6 @@ | |||
unit uutlInterfaces; | |||
{$mode objfpc}{$H+} | |||
{$modeswitch nestedprocvars} | |||
interface | |||
@@ -10,181 +9,74 @@ uses | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlEqualityComparer<T> = interface | |||
function EqualityCompare(const i1, i2: T): Boolean; | |||
end; | |||
generic TutlEqualityComparer<T> = class(TInterfacedObject, specialize IutlEqualityComparer<T>) | |||
public | |||
function EqualityCompare(const i1, i2: T): Boolean; | |||
end; | |||
generic TutlEventEqualityComparer<T> = class(TInterfacedObject, specialize IutlEqualityComparer<T>) | |||
public type | |||
TEqualityEvent = function(const i1, i2: T): Boolean; | |||
TEqualityEventO = function(const i1, i2: T): Boolean of object; | |||
TEqualityEventN = function(const i1, i2: T): Boolean is nested; | |||
private type | |||
TEqualityEventType = (eetNormal, eetObject, eetNested); | |||
private | |||
fEvent: TEqualityEvent; | |||
fEventO: TEqualityEventO; | |||
fEventN: TEqualityEventN; | |||
fEventType: TEqualityEventType; | |||
public | |||
function EqualityCompare(const i1, i2: T): Boolean; | |||
constructor Create(const aEvent: TEqualityEvent); overload; | |||
constructor Create(const aEvent: TEqualityEventO); overload; | |||
constructor Create(const aEvent: TEqualityEventN); overload; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
generic IutlEqualityComparer<T> = interface(IUnknown) | |||
['{C0FB90CC-D071-490F-BFEE-BAA5C94D1A5B}'] | |||
function EqualityCompare(constref i1, i2: T): Boolean; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlComparer<T> = interface | |||
function Compare(const i1, i2: T): Integer; | |||
end; | |||
generic TutlComparer<T> = class(TInterfacedObject, specialize IutlComparer<T>) | |||
public | |||
function Compare(const i1, i2: T): Integer; | |||
end; | |||
generic TutlEventComparer<T> = class(TInterfacedObject, specialize IutlComparer<T>) | |||
public type | |||
TEvent = function(const i1, i2: T): Integer; | |||
TEventO = function(const i1, i2: T): Integer of object; | |||
TEventN = function(const i1, i2: T): Integer is nested; | |||
private type | |||
TEventType = (etNormal, etObject, etNested); | |||
private | |||
fEvent: TEvent; | |||
fEventO: TEventO; | |||
fEventN: TEventN; | |||
fEventType: TEventType; | |||
public | |||
function Compare(const i1, i2: T): Integer; | |||
constructor Create(const aEvent: TEvent); overload; | |||
constructor Create(const aEvent: TEventO); overload; | |||
constructor Create(const aEvent: TEventN); overload; | |||
{ HINT: you need to activate "$modeswitch nestedprocvars" when you want to use nested callbacks } | |||
generic IutlComparer<T> = interface(specialize IutlEqualityComparer<T>) | |||
['{7D2EC014-2878-4F60-9E43-4CFB54268995}'] | |||
function Compare(constref i1, i2: T): Integer; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlReadOnlyList<T> = interface(IUnknown) | |||
function GetCount: Integer; | |||
function GetItem(const aIndex: Integer): T; | |||
generic IutlFilter<T> = interface(IUnknown) | |||
function Filter(constref i: T): Boolean; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic IutlList<T> = interface(specialize IutlReadOnlyList<T>) | |||
procedure SetItem(const aIndex: Integer; const aItem: T); | |||
generic IutlSelector<Tin, Tout> = interface(IUnknown) | |||
function Select(constref i: Tin): Tout; | |||
end; | |||
operator < (const i1, i2: TObject): Boolean; inline; | |||
operator > (const i1, i2: TObject): Boolean; inline; | |||
implementation | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator < (const i1, i2: TObject): Boolean; | |||
begin | |||
result := Pointer(i1) < Pointer(i2); | |||
end; | |||
generic TGenericArray<T> = array of T; | |||
generic IutlEnumerator<T> = interface(specialize IEnumerator<T>) | |||
function GetEnumerator: specialize IutlEnumerator<T>; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
operator > (const i1, i2: TObject): Boolean; | |||
begin | |||
result := Pointer(i1) > Pointer(i2); | |||
end; | |||
function Count: Integer; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlEqualityComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEqualityComparer.EqualityCompare(const i1, i2: T): Boolean; | |||
begin | |||
result := (i1 = i2); | |||
end; | |||
function Reverse: specialize IutlEnumerator<T>; | |||
function Skip (const aCount: Integer): specialize IutlEnumerator<T>; | |||
function Take (const aCount: Integer): specialize IutlEnumerator<T>; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEventEqualityComparer.EqualityCompare(const i1, i2: T): Boolean; | |||
begin | |||
case fEventType of | |||
eetNormal: result := fEvent(i1, i2); | |||
eetObject: result := fEventO(i1, i2); | |||
eetNested: result := fEventN(i1, i2); | |||
end; | |||
end; | |||
function Where (const aComparer: specialize IutlFilter<T>): specialize IutlEnumerator<T>; | |||
// TODO generic function Select<S> (const aSelector: specialize IutlSelector<T, S>): specialize IutlEnumerator<S>; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlEventEqualityComparer.Create(const aEvent: TEqualityEvent); | |||
begin | |||
inherited Create; | |||
fEvent := aEvent; | |||
fEventType := eetNormal; | |||
end; | |||
function ToArray: specialize TGenericArray<T>; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlEventEqualityComparer.Create(const aEvent: TEqualityEventO); | |||
begin | |||
inherited Create; | |||
fEventO := aEvent; | |||
fEventType := eetObject; | |||
end; | |||
generic IutlEnumerable<T> = interface(specialize IEnumerable<T>) | |||
['{963214EB-EF7C-4785-8B48-8DD9DE0ABDAF}'] | |||
function GetUtlEnumerator: specialize IutlEnumerator<T>; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlEventEqualityComparer.Create(const aEvent: TEqualityEventN); | |||
begin | |||
inherited Create; | |||
fEventN := aEvent; | |||
fEventType := eetNested; | |||
end; | |||
property UtlEnumerator: specialize IutlEnumerator<T> read GetUtlEnumerator; | |||
property Enumerator: specialize IEnumerator<T> read GetEnumerator; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlComparer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlComparer.Compare(const i1, i2: T): Integer; | |||
begin | |||
if (i1 < i2) then | |||
result := -1 | |||
else if (i1 > i2) then | |||
result := 1 | |||
else | |||
result := 0; | |||
end; | |||
generic IutlReadOnlyArray<T> = interface(IUnknown) | |||
['{B0938B6F-4E0D-45E3-A813-056AD4C0A2F2}'] | |||
function GetCount: Integer; | |||
function GetItem(const aIndex: Integer): T; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlEventComparer.Compare(const i1, i2: T): Integer; | |||
begin | |||
case fEventType of | |||
etNormal: result := fEvent(i1, i2); | |||
etObject: result := fEventO(i1, i2); | |||
etNested: result := fEventN(i1, i2); | |||
property Count: Integer read GetCount; | |||
property Items[const aIndex: Integer]: T read GetItem; default; | |||
end; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlEventComparer.Create(const aEvent: TEvent); | |||
begin | |||
inherited Create; | |||
fEvent := aEvent; | |||
fEventType := etNormal; | |||
end; | |||
generic IutlArray<T> = interface(specialize IutlReadOnlyArray<T>) | |||
['{D3618E88-3BF7-4E63-850F-6893A334564A}'] | |||
procedure SetCount(const aValue: Integer); | |||
procedure SetItem(const aIndex: Integer; aItem: T); | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlEventComparer.Create(const aEvent: TEventO); | |||
begin | |||
inherited Create; | |||
fEventO := aEvent; | |||
fEventType := etObject; | |||
end; | |||
property Count: Integer read GetCount write SetCount; | |||
property Items[const aIndex: Integer]: T read GetItem write SetItem; default; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlEventComparer.Create(const aEvent: TEventN); | |||
begin | |||
inherited Create; | |||
fEventN := aEvent; | |||
fEventType := etNested; | |||
end; | |||
implementation | |||
end. | |||
@@ -0,0 +1,166 @@ | |||
unit uutlListBase; | |||
{$mode objfpc}{$H+} | |||
interface | |||
uses | |||
Classes, SysUtils, | |||
uutlArrayContainer, uutlInterfaces; | |||
type | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
generic TutlListBase<T> = class( | |||
specialize TutlArrayContainer<T>, | |||
specialize IutlEnumerable<T>) | |||
strict private | |||
fCount: Integer; | |||
protected | |||
function GetCount: Integer; override; | |||
procedure SetCount(const aValue: Integer); override; | |||
function GetItem (const aIndex: Integer): T; virtual; | |||
procedure SetItem (const aIndex: Integer; aValue: T); virtual; | |||
procedure InsertIntern(const aIndex: Integer; constref aValue: T); virtual; | |||
procedure DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean); virtual; | |||
public { IutlEnumerable } | |||
function GetEnumerator: specialize IEnumerator<T>; | |||
function GetUtlEnumerator: specialize IutlEnumerator<T>; | |||
public | |||
property Count; | |||
property IsEmpty; | |||
property Capacity; | |||
property CanShrink; | |||
property CanExpand; | |||
property OwnsItems; | |||
procedure Clear; | |||
procedure ShrinkToFit; | |||
constructor Create(const aOwnsItems: Boolean); | |||
destructor Destroy; override; | |||
end; | |||
implementation | |||
uses | |||
uutlExceptions; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//TutlListBase////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlListBase.GetCount: Integer; | |||
begin | |||
result := fCount; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlListBase.SetCount(const aValue: Integer); | |||
begin | |||
if (aValue < Capacity) then | |||
Capacity := aValue; | |||
fCount := aValue; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlListBase.GetItem(const aIndex: Integer): T; | |||
begin | |||
if (aIndex < 0) or (aIndex >= Count) then | |||
raise EutlOutOfRange.Create(aIndex, 0, Count-1); | |||
result := GetInternalItem(aIndex)^; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlListBase.SetItem(const aIndex: Integer; aValue: T); | |||
var | |||
p: PT; | |||
begin | |||
if (aIndex < 0) or (aIndex >= Count) then | |||
raise EutlOutOfRange.Create(aIndex, 0, Count-1); | |||
p := GetInternalItem(aIndex); | |||
Release(p^, true); | |||
p^ := aValue; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlListBase.InsertIntern(const aIndex: Integer; constref aValue: T); | |||
var | |||
p: PT; | |||
begin | |||
if (aIndex < 0) or (aIndex > fCount) then | |||
raise EutlOutOfRange.Create(aIndex, 0, fCount); | |||
if (fCount = Capacity) then | |||
Expand; | |||
p := GetInternalItem(aIndex); | |||
if (aIndex < fCount) then | |||
System.Move(p^, (p+1)^, (fCount - aIndex) * SizeOf(T)); | |||
p^ := aValue; | |||
inc(fCount); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlListBase.DeleteIntern(const aIndex: Integer; const aFreeItem: Boolean); | |||
var | |||
p: PT; | |||
begin | |||
if (aIndex < 0) or (aIndex >= fCount) then | |||
raise EutlOutOfRange.Create(aIndex, 0, fCount-1); | |||
dec(fCount); | |||
p := GetInternalItem(aIndex); | |||
Release(p^, aFreeItem); | |||
System.Move((p+1)^, p^, SizeOf(T) * (fCount - aIndex)); | |||
if CanShrink and (Capacity > 128) and (fCount < Capacity shr 2) then // only 25% used | |||
SetCapacity(Capacity shr 1); // set to 50% Capacity | |||
FillByte(GetInternalItem(fCount)^, (Capacity-fCount) * SizeOf(T), 0); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlListBase.GetEnumerator: specialize IEnumerator<T>; | |||
begin | |||
result := GetUtlEnumerator; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
function TutlListBase.GetUtlEnumerator: specialize IutlEnumerator<T>; | |||
begin | |||
// TODO | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlListBase.Clear; | |||
begin | |||
while (Count > 0) do begin | |||
dec(fCount); | |||
Release(GetInternalItem(fCount)^, true); | |||
end; | |||
fCount := 0; | |||
if CanShrink then | |||
ShrinkToFit; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
procedure TutlListBase.ShrinkToFit; | |||
begin | |||
Shrink(true); | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
constructor TutlListBase.Create(const aOwnsItems: Boolean); | |||
begin | |||
inherited Create(aOwnsItems); | |||
fCount := 0; | |||
end; | |||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
destructor TutlListBase.Destroy; | |||
begin | |||
Clear; | |||
inherited Destroy; | |||
end; | |||
end. | |||