| @@ -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. | |||