├── .gitignore ├── CHANGELOG.md ├── CREDITS.md ├── LICENSE-delphi-coll-xe.txt ├── LICENSE-delphi-coll.txt ├── LICENSE.md ├── README.md ├── Tidy.bat ├── doc ├── CollectionDetails.md ├── DifferencesFromGenericsCollections.md ├── EnexOperations.md └── FAQ.md ├── media ├── AssocCollectionsDiagram.png ├── Collection Diagram.docx ├── Logo-XE.pdn ├── Logo-XE.png ├── SimpleCollectionsDiagram.png ├── Simplified Diagram.docx └── SimplifiedClassDiagram.png └── src ├── Collections Projects.groupproj ├── Library ├── Collections.Bags.pas ├── Collections.Base.pas ├── Collections.BidiDictionaries.pas ├── Collections.BidiMaps.pas ├── Collections.Dictionaries.pas ├── Collections.Dynamic.pas ├── Collections.Lists.pas ├── Collections.MultiMaps.pas ├── Collections.Queues.pas ├── Collections.Serialization.pas ├── Collections.Sets.pas ├── Collections.Stacks.pas ├── Collections.dpk ├── Collections.dproj ├── Collections.res └── Collections_Icon.ico ├── Samples ├── Joining.pas ├── List_Store_Load.pas ├── Op_Select_View.pas ├── Samples.dpr ├── Samples.dproj ├── Samples.res ├── Sort_Person.pas └── SplitStringEnumerable.pas └── Tests ├── Tests.Conformance.Bags.pas ├── Tests.Conformance.Base.pas ├── Tests.Conformance.BidiDictionaries.pas ├── Tests.Conformance.BidiMaps.pas ├── Tests.Conformance.Dictionaries.pas ├── Tests.Conformance.Lists.pas ├── Tests.Conformance.MultiMaps.pas ├── Tests.Conformance.Queues.pas ├── Tests.Conformance.Sets.pas ├── Tests.Conformance.Specific.pas ├── Tests.Conformance.Stacks.pas ├── Tests.Internal.Basics.pas ├── Tests.Internal.Dynamic.pas ├── Tests.Internal.Serialization.pas ├── Tests.dpr ├── Tests.dproj ├── Tests.res └── Tests_Icon.ico /.gitignore: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 GitHub, Inc. 2 | 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and associated documentation files (the "Software"), 5 | # to deal in the Software without restriction, including without limitation 6 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | # and/or sell copies of the Software, and to permit persons to whom the 8 | # Software is furnished to do so, subject to the following conditions: 9 | 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | # DEALINGS IN THE SOFTWARE. 20 | 21 | # ------------------------------------------------------------------------------ 22 | # This file is a modification of Delphi.gitignore (commit 23 | # fe00bd78b8e0b86cd9124c96588ee9f056801042) from the github/gitignore project on 24 | # GitHub. 25 | # ------------------------------------------------------------------------------ 26 | 27 | # Uncomment these types if you want even more clean repository. But be careful. 28 | # It can make harm to an existing project source. Read explanations below. 29 | # 30 | # Resource files are binaries containing manifest, project icon and version 31 | # info. They can not be viewed as text or compared by diff-tools. Consider 32 | # replacing them with .rc files. 33 | #*.res 34 | # 35 | # Type library file (binary). In old Delphi versions it should be stored. 36 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 37 | #*.tlb 38 | # 39 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 40 | # Uncomment this if you are not using diagrams or use newer Delphi version. 41 | #*.ddp 42 | # 43 | # Visual LiveBindings file. Added in Delphi XE2. 44 | # Uncomment this if you are not using LiveBindings Designer. 45 | #*.vlb 46 | # 47 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 48 | # Uncomment this if it is not mobile development and you do not use remote debug 49 | # feature. 50 | #*.deployproj 51 | # 52 | # C++ object files produced when C/C++ Output file generation is configured. 53 | # Uncomment this if you are not using external objects (zlib library for 54 | # example). 55 | #*.obj 56 | # 57 | 58 | # Delphi compiler-generated binaries (safe to delete) 59 | *.exe 60 | *.dll 61 | *.bpl 62 | *.bpi 63 | *.dcp 64 | *.so 65 | *.apk 66 | *.drc 67 | *.map 68 | *.dres 69 | *.rsm 70 | *.tds 71 | *.dcu 72 | *.lib 73 | *.a 74 | *.o 75 | *.ocx 76 | 77 | # Delphi autogenerated files (duplicated info) 78 | *.cfg 79 | *.hpp 80 | *Resource.rc 81 | 82 | # Delphi local files (user-specific info) 83 | *.local 84 | *.identcache 85 | *.projdata 86 | *.tvsconfig 87 | *.dsk 88 | 89 | # Delphi history and backups 90 | __history/ 91 | *.~* 92 | 93 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 94 | *.stat 95 | 96 | # ------------------------------------------------------------------------------ 97 | # Items below here added by DelphiDabbler exclusively for the delphi-coll 98 | # project 99 | # ------------------------------------------------------------------------------ 100 | 101 | bin 102 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | v1.0 to v1.2 were released from the original `pavkam/delphi-coll` project. These releases were not dated and neither did they appear to follow the [Semantic Versioning](http://semver.org/) model. 6 | 7 | v2.0.0-alpha.1 and later were released from the `delphidabbler/delphi-coll-xe` fork. They adhere to the principles of [Semantic Versioning](http://semver.org/). 8 | 9 | ## v2.0.0-alpha.1 of 2022-05-24 10 | 11 | ### Changes made on `pavkam/delphi-coll` 12 | 13 | > The following is a guesstimate of the changes made to the `pavkam/delphi-coll` repository following the release of v1.2 up until the project was forked. This list is not guaranteed to be complete or totally accurate. 14 | 15 | * Various renamings: 16 | * `TEnexAssociativeCollection` as `TAssociation`; 17 | * `IEnexAssociativeCollection` as `IAssociation`; 18 | * `TEnexCollection` as `TSequence`; 19 | * `IEnexCollection` as `ISequence`; 20 | * `TCollection` as `TContainer`; 21 | * `ICollection` as `IContainer`; 22 | * `TAbstractCollection` as `TAbstractContainer`; 23 | * `TAbstractCollection` as `TAbstractContainer`; 24 | * `TOperableCollection` as `TCollection`; 25 | * `IOperableCollection` as `ICollection`; 26 | * `[NonSerializable]` attribute as `[NonSerialized]`. 27 | * Removed `GroupedBy()` extended operation added in v1.1. 28 | 29 | ### Changes made on `delphidabbler/delphi-coll-xe` 30 | 31 | > The following changes were made to the `delphidabbler/delphi-coll-xe` repository after the project was forked from `pavkam/delphi-coll`. 32 | 33 | * Fixed unit tests to enable compilation and to prevent test running from crashing when running some tests. Many of the changes were required because of the interface and class name changes noted above. **Note:** No attempt was made to make any failed tests pass or to complete missing tests -- the changes were simply to get the test runner compiled and running. 34 | * Documentation changes: 35 | * Added documentation recovered from former project wiki on *GoogleCode*. Documents were recovered by using the Internet Archive. 36 | * Rewrote read-me. 37 | * Added credits file listing contributors. 38 | * Revised license information in light of project fork. 39 | * Converted change log to markdown format. 40 | * Removed outdated help file and its source documents. 41 | * Fixed problem with project options that was causing AV fault in Delphi XE IDE. 42 | * Removed modeling files. 43 | * Fixed *Samples* project to work around an apparent Delphi XE compiler bug. 44 | * New batch file to delete temporary files from source tree. 45 | * Build number in library version information no longer auto-increments on each build. 46 | 47 | ## v1.2 48 | 49 | * New unit `Collections.Serialization`. Includes: 50 | 1. `TSerializer` - a semi-abstract class that implementes generic serialization. 51 | 2. `TDeserializer` - a semi-abstract class that implements generic deserialization. 52 | 3. `ISerializable` - an interface can be implemented by classes that need to override the default serialization. 53 | 4. `TInputContext`/`TOutputContext` - two facade objects that only expose a few operations to classes through `ISerializable`. 54 | 5. `[NonSerializable]` - the attribute to marks field that should not be serialized. 55 | 6. Two concrete implementations for serialization in implementation section! 56 | * Some documentation fixes all over the place. 57 | * Removed the `ICollectionMap` interface. It made no sense in the hierarchy. Its methods were split between the two interfaces that inherited it. 58 | * Added a new interface `ILinkedList` currently implemented by `TLinkedList` and `TSortedLinkedList`. 59 | * Removed `Copy` methods from `TList`. 60 | * Removed sorting, reversing and copy methods from `TLinkedList`. That was a mistake anyway. 61 | * Added `TAbstractSet` from which all sets derive. 62 | * Added `TAbstractStack` from which all stacks derive. 63 | * Added `TAbstractQueue` from which all queues derive. 64 | * Added `TAbstractDictionary` from which all dictionaries derive. This allowed us to remove a lot of duplicated code. 65 | * Added `TAbstractList` from which `TList` derives. 66 | * Added `TAbstractLinkedList` derived from `TAbstractList` from which `TLinkedList` derives. 67 | * `TSortedList` extends `TList` now while `TSortedLinkedList` extends `TLinkedList`. Removed a lot of duplicated code. 68 | * Removed `ISortedList`. There's nothing I can put in there to make it useful. 69 | * `TLinkedList` and `TSortedLinkedList` implement `IQueue` and `IStack`. A linked list can be used as both these collections transparently. 70 | * `TCollection` base class supports versioning out of the box. 71 | * `TEnumerator` base class was renamed to `TAbstractEnumerator` and completely revamped. It is now much more simple to extend and also provides version checking out of the box. 72 | * `TForwardingEnumerator` is a special class that uses another enumerator as base. 73 | * Renamed `IEnexGroupingCollection` as `IGrouping`. 74 | * Rewrote all enumerators in the package to use the new interface. 75 | * Introduced a new non-generic `TAbstractCollection`. `TAbstractCollection` derives from it. 76 | * Added `IOperableCollection` that exposes `Add`, `AddAll`, `Remove`, `RemoveAll`, `Contains`, `ContainsAll` and `Clear` methods. 77 | * Added `TOperableCollection` with default implementation of `IOperableCollection`. All simple types adjusted accordingly. 78 | * `IList.Insert(Collection)` renamed to `InsertAll`. `Add(Collection)` renamed to `AddAll`. 79 | * `ILinkedList.AddLast(Collection)` renamed to `AddAllLast`. `AddFirst` renamed to `AddAllFirst`; 80 | * New `TAbstractMap` collection which is a base class for all associative maps. 81 | * All collections now have only 3 constructors: 82 | 1. The default parameterless one. 83 | 2. The one that accepts the rule set (or sets for associative). 84 | 3. The one that accepts the rule set(s) and additional information that can be: 85 | 1. Sorting of elements/keys. 86 | 2. Sorting of keys and sorting of values. 87 | 3. Initial capacity. 88 | 4. Initial capacity and sorting of elements/keys. 89 | * Reworked the interface of `IBag` to accommodate the new changes. 90 | 91 | ## v1.1.1 92 | 93 | * All lists and dictionaries now posses a `ExtractAt` or `Extract` or `ExtractKey`, `ExtractValue` methods. These function exactly as remove but do not trigger cleanup for objects. 94 | * Fix: `TObjectMultiMap` required a class for it's value type parameter. 95 | * Fix: `RemoveKey`/`RemoveValue` for `Bidi` dictionaries were not calling the cleaning handler. 96 | 97 | ## v1.1 98 | 99 | * Started a new project: `Samples`. A few samples have been added for your delight. 100 | * Implemented `T(Object)LinkedDictionary` that used a hash/linked list approach. Guarantees insert order preservation of elements. 101 | * Implemented `T(Object)LinkedSet` that used a hash/linked list approach. Guarantees insert order preservation of elements. 102 | * `TBitSet`, a new Word-only type that uses an internal array of bits. 103 | * New unit `Collection.BidiDictionaries` contains a number of dictionary types that enforce both key to value and value to key rules. 104 | * `TBidiDictionary` 105 | * `TSortedBidiDictionary` 106 | * `TDoubleSortedDictionary` 107 | * Added a new unit: `Collections.Dynamic`. This unit exposes a simple Member record that allows generating selectors for class/record members. 108 | * `TView` is a small type that can hold a number of fields/properties from a object or record. Look at it as anonymous classes in C#. It's not that pretty but it does the job in some cases. 109 | * Implement `T(Object)SortedLinkedList`. This class uses a linked list to store its elements. It also implements `IList` interface and provides access to the index based functions (slow). 110 | * Added `ISortedSet` interface now implemented by `TSortedSet`. 111 | * Added three new overloads to `Op.Select` (one with preset output type, one for `TValue` output and one for `TView` output). 112 | * New `GroupedBy()` extended operation and `IEnexGroupingCollection`. 113 | * Removed `IUnorderedList`. All lists implement `IList` now (that includes `Insert`!). 114 | * `IList` now includes `Insert()`. 115 | * Renamed `IOrderedList` into `ISortedList`. 116 | * `TLinkedStack` now uses an internal linked list and not the much "loved" `TLinkedList` class. This should bring quite some speed improvements into the game. 117 | * `TLinkedQueue` now uses an internal linked list and not the much "loved" `TLinkedList` class. This should bring quite some speed improvements into the game. 118 | * `TLinkedList` was completely rewritten. It's no longer .NET-like, it looks just like a simple `TList` but stores its elements in a linked list. A lot of indexing methods are supported but are dead slow! 119 | * `TArraySet` is not a sorted set. It's been optimized. 120 | * `TSortedList`'s methods have been optimized to use binary search. 121 | * Optimized `TList.Add(collection)` a lot. Should be a big boost to all dependent functions. 122 | * Updated multiple tests. Added missing test cases for `TArraySet`. 123 | * Fixed a few bugs related to `IndexOf` in empty collections. Regression tests added. 124 | * Fixed an error in `TDictionary` and `THashSet` where initial capacity size was set to zero. 125 | * Fixed `TSortedList.Copy` to also copy the ascending/descending flag from the original list. 126 | * Fixed some documentation (removed "cleaning" references). 127 | * Fixed a bug in all dictionary implementations related to the way values were replaced. Memory leaks would appear. Regression tests added. 128 | * Fixed a bug in all list implementations related to the way values were replaced. Memory leaks would appear. Regression tests added. 129 | 130 | ## v1.0.1 131 | 132 | * Do not expose `AreEqual`, `Compare` and `GetHashCode` in `TRules`. 133 | * Add protected methods `ElementsAreEqual`, `CompareElements`, `GetElementHashCode` to `TEnexCollection`. 134 | * Add protected methods `KeysAreEqual`, `CompareKeys`, `GetKeyHashCode` to `TEnexAssociativeCollection`. 135 | * Add protected methods `ValuesAreEqual`, `CompareValues`, `GetValueHashCode` to `TEnexAssociativeCollection`. 136 | * Do not use `ElementRules`, `KeyRules` and `ValueRules` in code directly. 137 | * Define `EArgumentNilException` if RTL version is less than 22 (2010). 138 | * Fixed grammar and spelling errors (by Denisa Ilascu). 139 | 140 | ## v1.0 141 | 142 | * First public version! 143 | * The following units are provided 144 | * `Collections.Base` 145 | * `Collections.Lists` 146 | * `Collections.Queues` 147 | * `Collections.Stacks` 148 | * `Collections.Sets` 149 | * `Collections.Dictionaries` 150 | * `Collections.Bags` 151 | * `Collections.MultiMaps` 152 | * `Collections.BidiMaps` 153 | * Documentation is up. 154 | * Everything is tested. 155 | -------------------------------------------------------------------------------- /CREDITS.md: -------------------------------------------------------------------------------- 1 | # delphi-coll-xe Credits 2 | 3 | *delphidabbler/delphi-coll-xe* is based on a fork of the *pavkam/delphi-coll* project that was created and largely written by [Ciobanu Alexandru](https://github.com/pavkam). 4 | 5 | Other known contributors to the original project were: 6 | 7 | * D Atamanov 8 | * Denisa Ilascu 9 | 10 | The *delphidabbler/delphi-coll-xe* fork was created by [Peter Johnson](http://en.gravatar.com/delphidabbler), who has contributed to the code. 11 | -------------------------------------------------------------------------------- /LICENSE-delphi-coll-xe.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Peter Johnson (@delphidabbler) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /LICENSE-delphi-coll.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2012, Ciobanu Alexandru. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | * Neither the name of the this library nor the 11 | names of its contributors may be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 15 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # delphi-coll-xe License Overview 2 | 3 | ## Main Licenses 4 | 5 | This project *(delphidabbler/delphi-coll-xe)* is based on a fork of an original project - [pavkam/delphi-coll](https://github.com/pavkam/delphi-coll). 6 | 7 | All source code in this project that originates from *pavkam/delphi-coll* is copyright [Ciobanu Alexandru](https://github.com/pavkam) and licensed under the 3 clause BSD license. This license also applies to any modifications of the original files. Full details of this license can be found in the file `LICENSE-delphi-coll.txt`. 8 | 9 | All non-third party source code that was newly created for the *delphidabler/delphi-coll-xe* project is copyright [Peter Johnson](https://github.com/delphidabbler) and is also licensed under the 3 clause BSD license. For details of this license see the file `LICENSE-delphi-coll-xe.txt`. 10 | 11 | Source code files contain the text of the relevant license. 12 | 13 | Both of the above license files must be included in any binary distributions of *delphi-coll-xe*. 14 | 15 | ## Other Licenses 16 | 17 | *delphi-coll-xe* makes use of some 3rd party source code, as follows: 18 | 19 | * `./.gitignore` is licensed under the [MIT license](https://opensource.org/licenses/MIT) and is copyright (c) 2016, *GitHub*. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # delphi-coll-xe 2 | 3 | Generic collections for Delphi XE and later. 4 | 5 | > This project is based on a fork of the **discontinued** *delphi-coll* project *(Delphi Collections Library)* by Ciobanu Alexandru. See below for further information. 6 | 7 | ## Overview of the library 8 | 9 | ### Description 10 | 11 | The *Delphi Collections Library XE* is a package consisting of basic and advanced generic collections for Delphi. This package uses Delphi's standard `Generics.Defaults` and `Generics.Collections` units to access the comparer and equality comparer functionality. The library classes **do not** inherit from the base classes in `Generics.Collections`. 12 | 13 | The library is fully documented using XMLDoc in the source code. You can use Help Insight from the Delphi IDE to view function, type and class descriptions directly from the IDE. 14 | 15 | DUnit unit tests are available for some of the code. 16 | 17 | ### Requirements 18 | 19 | At least Delphi XE is required for the library to function. 20 | 21 | ### Diagrams 22 | 23 | ![Simple collections diagram](media/SimpleCollectionsDiagram.png) 24 | 25 | ![Associative collections diagram](media/AssocCollectionsDiagram.png) 26 | 27 | ### More info 28 | 29 | * [FAQ](doc/FAQ.md) 30 | * [Implementation details](doc/CollectionDetails.md) 31 | * [Enex operations](doc/EnexOperations.md) 32 | * [Difference from standard collections](doc/DifferencesFromGenericsCollections.md) 33 | * [Change log](CHANGELOG.md) 34 | 35 | ## Information about the original project 36 | 37 | This project was forked from [*Delphi Collections Library*](https://github.com/pavkam/delphi-coll) by [Ciobanu Alexandru](https://github.com/pavkam). This project was discontinued on 09 January 2012. 38 | 39 | The code from which this fork is derived is based on [commit 6f4c499](https://github.com/pavkam/delphi-coll/commit/6f4c499dafa1fdb59004cfbeafc34bd5d45bbfed) of the *Delphi Collections Library*. This commit represents a point in time following release v1.2 after some API breaking changes had been made. 40 | 41 | ## License 42 | 43 | See [LICENSE.md](LICENSE.md) for full details. 44 | 45 | ## Contributing 46 | 47 | Future development will be using the [Git Flow](http://nvie.com/posts/a-successful-git-branching-model/) branching model. So, to contribute please create a feature branch off the `develop` branch, make your changes, and then create a pull request for your changes. 48 | 49 | ## Bugs 50 | 51 | Please notify any bugs using the [GitHub Issue Tracker](https://github.com/delphidabbler/delphi-coll-xe/issues). 52 | 53 | **Note:** This is not a top priority project for me, so I may not fix all bugs. So, if you can, fix the bug yourself and submit your changes. Pull requests are the way to go -- see above. 54 | 55 | > Using the *Wayback Machine*, a list of [outstanding issues](http://web.archive.org/web/20140312003357/http://code.google.com/p/delphi-coll/issues/list) from the original *Delphi Collections Library* project has been found. Unfortunately the issue detail pages are not archived, so all we have are brief descriptions of each issue, which means there's not much to go on. 56 | -------------------------------------------------------------------------------- /Tidy.bat: -------------------------------------------------------------------------------- 1 | @rem * Copyright (c) 2016, Peter Johnson (@delphidabbler) 2 | @rem * All rights reserved. 3 | @rem * 4 | @rem * Redistribution and use in source and binary forms, with or without 5 | @rem * modification, are permitted provided that the following conditions are 6 | @rem * met: 7 | @rem * 8 | @rem * 1. Redistributions of source code must retain the above copyright notice, 9 | @rem * this list of conditions and the following disclaimer. 10 | @rem * 11 | @rem * 2. Redistributions in binary form must reproduce the above copyright 12 | @rem * notice, this list of conditions and the following disclaimer in the 13 | @rem * documentation and/or other materials provided with the distribution. 14 | @rem * 15 | @rem * 3. Neither the name of the copyright holder nor the names of its 16 | @rem * contributors may be used to endorse or promote products derived from 17 | @rem * this software without specific prior written permission. 18 | @rem * 19 | @rem * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 | @rem * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | @rem * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | @rem * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 23 | @rem * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | @rem * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | @rem * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | @rem * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | @rem * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | @rem * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | @rem * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | 32 | @echo off 33 | 34 | setlocal 35 | 36 | set RootDir=. 37 | 38 | echo Deleting temporary files 39 | 40 | del /S %RootDir%\*.~* 41 | del /S %RootDir%\*.bak 42 | del /S %RootDir%\*.ddp 43 | del /S %RootDir%\*.dsk 44 | del /S /AH %RootDir%\*.GID 45 | del /S %RootDir%\*.identcache 46 | del /S %RootDir%\*.local 47 | del /S %RootDir%\*.tmp 48 | echo. 49 | 50 | echo Deleting build and history sub-directories 51 | 52 | if exist %RootDir%\bin rmdir /S /Q %RootDir%\bin 53 | 54 | for /F "usebackq" %%i in (`dir /S /B /A:D %RootDir%\__history*`) do rmdir /S /Q %%i 55 | 56 | echo Done. 57 | 58 | endlocal 59 | -------------------------------------------------------------------------------- /doc/DifferencesFromGenericsCollections.md: -------------------------------------------------------------------------------- 1 | # Differences From Generics Collections 2 | 3 | > This document is a Markdown conversion of a page from the original *delphi-coll* project's *GoogleCode* wiki. The original was recovered from a [Wayback machine snapshot](http://web.archive.org/web/20130521194411/http://code.google.com/p/delphi-coll/wiki/DifferencesFromGenericsCollections) of 21 May 2013 and was last updated on 25 January 2011 by *denisa.i...@gmail.com*. 4 | 5 | ## Introduction 6 | 7 | This page details the differences between the `Collections` package and the `Generics.Collections` standard unit. 8 | 9 | ## Rule sets 10 | 11 | The `Generics.Defaults` unit defines two basic interfaces used to represent a type (compare and hash code). These are: 12 | 13 | * `IComparer`, which provides support for comparing two values of the same type. 14 | * `IEqualityComparer`, which provides support for comparing for equality and generating a hash code for a given value. 15 | 16 | While the first type is used for collections that at some point need comparing their elements (with requiring a sort order), the second type is used mainly in hash-based collections such as `TDictionary`. 17 | 18 | All collections in the `Collections` package always require the possibility to compare two elements, so `IComparer` is a must have type. Some collections such as `TDictionary` and `THashSet` also require an `IEqualityComparer` type for its hashing functionality. This basically means that in most cases you will require to pass both types to a collection in order to make it fully functional. 19 | 20 | To alleviate this need, the `Collections` package introduces `TRules`, which is a simple record type that contains both a comparer and an equality comparer (on need basis). To obtain a set of rules, one must call the `TRules.Default` method, which retrieves the default comparer and the equality comparer from the `Generics.Collections` system. 21 | 22 | ## Base classes 23 | 24 | `Generics.Collections` classes are all derived from `TEnumerable` or `TEnumerator`. Most people will agree that this is not enough in many cases and that is why `Collections` introduces interfaces. All collections have a public interface (e.g. `IList`, `IDictionary`, and so on). Also, since there exists more than one implementation for the same collection idea, an interface is a must. For example, there is a hash-based `TDictionary` type and an AVL tree based-one, `TSortedDictionary`. 25 | 26 | All collections in this package ultimately descend from either `TSequence` (non-associative collections) or `TAssociation` (associative collections), both of which descend from `TAbstractContainer`. There is no restriction that new collections must do the same, though it is still recommended, because the base classes implement most extended enumerable operations out-of-the-box. 27 | 28 | ## Enumerable extensions (ENEX) 29 | 30 | All collections in the proposed package support a set of extensions. Because Delphi does not support proper class helpers, it was necessary to provide interface-based extensions. In any case, there are a large number of helper functions each collection implements / re-implements or extends, giving the user total freedom and optimizing a lot of things that would take a lot of time otherwise. For example, to obtain a list of distinct elements in a list, one can simple call `LList.Distinct().ToList()`, which otherwise would have taken a bit of coding to write. 31 | 32 | For more information regarding ENEX, see `ISequence` and `IAssociation` in the `Collections.Base` unit. 33 | 34 | ## Integer vs NativeInt 35 | 36 | `Collections` relies on `NativeInt` extensively in the code. You won't find any references to `Integer`. This is a personal preference and is designed to more easily enable 64bit support when it's ready. 37 | -------------------------------------------------------------------------------- /doc/FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQs 2 | 3 | > This document is a Markdown conversion of a page from the original *delphi-coll* project's *GoogleCode* wiki. The original was recovered from a [Wayback machine snapshot](http://web.archive.org/web/20140313054413/http://code.google.com/p/delphi-coll/wiki/FAQ) of 13 March 2013 and was last updated on 03 February 2011 by *denisa.i...@gmail.com*. 4 | 5 | ## Introduction 6 | 7 | A list of frequently asked questions about the *delphi-coll* project. 8 | 9 | ## The Questions 10 | 11 | ### Why *Collections* and not stock collections? 12 | 13 | This is the wrong question to be asking yourself. The correct question would be "Am I satisfied with stock Delphi collections?". If your answer is no, then you have come to the right place. Check out the source code or browse around this portal a bit to find out what this project offers you. If you think you found valuable code that will make your life easier -- then use it, otherwise move on. 14 | 15 | ### I don't trust open source projects. Why should I use this one? 16 | 17 | If you don't trust open source then don't. But bear in mind that this project has more than two years in progress (initially part of the *DeHL* project). All functionality has associated extensive unit tests. And every API has inline XMLDoc available explaining the purpose, use case and event possible exceptions that can be generated. 18 | 19 | ### What is the performance gain over stock collections? 20 | 21 | None. The main focus of this project is to bring quality, simplicity, and most of all consistency on the table. Stock Delphi collections are designed to give you speed and simplicity while ignoring consistency. 22 | 23 | ### I care about speed. Why don't you care about that? 24 | 25 | Sure I care. You can see it in a lot of places in my code. But I do not want to sacrifice consistency and design for a few gained cycles. If your project requires 100% performance then hand writing by case collections is your best bet anyway. 26 | 27 | ### Who needs so many collection types anyway? 28 | 29 | Everybody and nobody at the same time. This project provides the basic set of collections everybody loves (for example, `TList`, `TStack`, `TDictionary`, `THashSet`). But there are numerous cases when specific variations or combination of these are required. I am pretty sure most of us needed a multi-map at some point or another and we always chose to write it by combining a dictionary with a number of lists. The point I am making is that there are many types of needs out there, and this project tries to provide them all as best as possible. 30 | 31 | ### Can I port my project to *Collections* from the stock collections? 32 | 33 | First check if your project really needs the functionality provided by this project. Is porting over to *Collections* going to save you a large number of lines of code? Are you going to remove a lot of old legacy cruft? Then yes, you can move over to *Collections*. In all other cases I do not recommend it. 34 | 35 | ### What is this `TRules` I see? 36 | 37 | All classes in *Collections* require a comparer and some require an equality comparer. When and how is a little tricky to find, so there is a special type called `TRules` that encapsulates a comparer and an equality comparer. Look at `TRules` simply as a combination of those two. 38 | 39 | ### What the heck is that ENEX thingy? 40 | 41 | Enex stands short for Enumerable Extensions. This is a set of operations that can be applied to all collections provided by this project. This is one of the main attractions of this project, as it allows the programmer worry about the program and not some menial collection-related task. See the samples included in the source code to get a better idea. 42 | 43 | ### Why so many interfaces? I don't like using them in my code. 44 | 45 | Interfaces are required for Enex functionality. Enex relies on chaining collections and pseudo-collections. There are also a large number of implementations for the same collection type (for example, `TDictionary`, `TLinkedDictionary`, or `TSortedDictionary`, which all implement `IDictionary`). In order to make "runtime" selection of implementations easier, interfaces are a great help. 46 | 47 | ### Do I have to use interfaces then? 48 | 49 | No. You can use just classes. *Collections* will not impose any particular style on you. 50 | 51 | ### Why do I get an Internal Compiler Error when I try X? 52 | 53 | I am truly sorry. I have a really big "unorthodox" test case set that I always try to run to ensure that both the code is correct and that the project properly compiles. While I try to avoid ICEs (internal compiler errors) they still squeeze through in circumstances that I cannot predict. If you find such a case, create a small test case and add an issue. I will do my best to fix the problem either by offering advice on how to avoid the ICE or by changing something in the code. 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /media/AssocCollectionsDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/AssocCollectionsDiagram.png -------------------------------------------------------------------------------- /media/Collection Diagram.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/Collection Diagram.docx -------------------------------------------------------------------------------- /media/Logo-XE.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/Logo-XE.pdn -------------------------------------------------------------------------------- /media/Logo-XE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/Logo-XE.png -------------------------------------------------------------------------------- /media/SimpleCollectionsDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/SimpleCollectionsDiagram.png -------------------------------------------------------------------------------- /media/Simplified Diagram.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/Simplified Diagram.docx -------------------------------------------------------------------------------- /media/SimplifiedClassDiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/media/SimplifiedClassDiagram.png -------------------------------------------------------------------------------- /src/Collections Projects.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {34AD8257-AF37-4EFE-B6E2-8C040CBC96C1} 4 | 5 | 6 | 7 | 8 | 9 | 10 | Library\Collections.dproj 11 | 12 | 13 | Library\Collections.dproj 14 | 15 | 16 | 17 | Default.Personality.12 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/Library/Collections.Dynamic.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011-2012, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | unit Collections.Dynamic; 29 | interface 30 | {$IF CompilerVersion > 21} 31 | uses 32 | SysUtils, 33 | Generics.Collections, 34 | Rtti, 35 | TypInfo; 36 | 37 | type 38 | /// Alias for the Rtti TValue type. The compiler seems to have a hard 39 | /// time differentiating TValue from the generic TValue type argument. 40 | TAny = TValue; 41 | 42 | /// An alias to the Variant type. Its main purpose is to serve as a reminder that 43 | /// it contains a part of an object. It is to be considered a "dynamic record". 44 | TView = Variant; 45 | 46 | /// A special purpose record type that exposes a number of methods that generate 47 | /// selector methods for fields and properties of a class or record type. 48 | Member = record 49 | private class var 50 | FViewVariantType: Word; 51 | 52 | private type 53 | {$REGION 'Internal Types'} 54 | TViewPair = TPair; 55 | TViewArray = TArray; 56 | 57 | TSelector = class(TInterfacedObject, TFunc, TFunc) 58 | private 59 | FContext: TRttiContext; 60 | FType: TRttiType; 61 | FMember: TRttiMember; 62 | 63 | protected 64 | function TFunc.Invoke = GenericInvoke; 65 | function TFunc.Invoke = TValueInvoke; 66 | 67 | public 68 | function TValueInvoke(AFrom: T): TValue; virtual; abstract; 69 | function GenericInvoke(AFrom: T): K; 70 | end; 71 | 72 | TRecordFieldSelector = class(TSelector) 73 | public 74 | function TValueInvoke(AFrom: Pointer): TValue; override; 75 | end; 76 | 77 | TClassFieldSelector = class(TSelector) 78 | public 79 | function TValueInvoke(AFrom: TObject): TValue; override; 80 | end; 81 | 82 | TClassPropertySelector = class(TSelector) 83 | public 84 | function TValueInvoke(AFrom: TObject): TValue; override; 85 | end; 86 | 87 | TViewSelector = class(TInterfacedObject, TFunc) 88 | private 89 | FNames: TArray; 90 | FFuncs: TArray>; 91 | public 92 | function Invoke(AFrom: T): TView; 93 | end; 94 | 95 | {$ENDREGION} 96 | 97 | public 98 | /// Generates a selector for a given member name. 99 | /// The field or property name to select from T. 100 | /// A selector function that retrieves the field/property from a class or record. 101 | /// nil is returned in case of error. 102 | class function Name(const AName: string): TFunc; overload; static; 103 | 104 | /// Generates a selector for a given member name. 105 | /// The field or property name to select from T. 106 | /// A selector function that retrieves the field/property from a class or record. The selected value is a TValue type. 107 | /// nil is returned in case of error. 108 | class function Name(const AName: string): TFunc; overload; static; 109 | 110 | /// Generates a selector for the given member names. 111 | /// The field or property names to select from T. 112 | /// A selector function that retrieves the fields/properties from a class or record. The selected value is a TView type. 113 | /// nil is returned in case of error. 114 | class function Name(const ANames: array of string): TFunc; overload; static; 115 | end; 116 | 117 | implementation 118 | uses 119 | Variants; 120 | 121 | type 122 | { Mapping the TSVDictionary into TVarData structure } 123 | TViewDictionaryVarData = packed record 124 | { Var type; will be assigned at run time } 125 | VType: TVarType; 126 | { Reserved stuff } 127 | Reserved1, Reserved2, Reserved3: Word; 128 | { A reference to the enclosed dictionary } 129 | FArray: Member.TViewArray; 130 | { Reserved stuff } 131 | Reserved4: LongWord; 132 | {$IFDEF CPUX64} 133 | Reserved4_1: LongWord; 134 | {$ENDIF} 135 | end; 136 | 137 | { Manager for our variant type } 138 | TViewDictionaryVariantType = class(TInvokeableVariantType) 139 | public 140 | procedure Clear(var V: TVarData); override; 141 | procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean); override; 142 | function GetProperty(var Dest: TVarData; const V: TVarData; const Name: string): Boolean; override; 143 | end; 144 | 145 | { TViewDictionaryVariantType } 146 | 147 | procedure TViewDictionaryVariantType.Clear(var V: TVarData); 148 | begin 149 | { Clear the variant type } 150 | V.VType := varEmpty; 151 | 152 | { And dispose the value } 153 | TViewDictionaryVarData(V).FArray := nil; 154 | end; 155 | 156 | procedure TViewDictionaryVariantType.Copy(var Dest: TVarData; 157 | const Source: TVarData; const Indirect: Boolean); 158 | begin 159 | if Indirect and VarDataIsByRef(Source) then 160 | VarDataCopyNoInd(Dest, Source) 161 | else 162 | begin 163 | with TViewDictionaryVarData(Dest) do 164 | begin 165 | { Copy the variant type } 166 | VType := VarType; 167 | 168 | { Copy the reference } 169 | FArray := TViewDictionaryVarData(Source).FArray; 170 | end; 171 | end; 172 | end; 173 | 174 | function TViewDictionaryVariantType.GetProperty(var Dest: TVarData; const V: TVarData; const Name: string): Boolean; 175 | var 176 | LPair: Member.TViewPair; 177 | LAsVar: Variant; 178 | begin 179 | { Iterate over our internal array and search for the requested property by name } 180 | with TViewDictionaryVarData(V) do 181 | begin 182 | for LPair in FArray do 183 | if AnsiSameStr(LPair.Key, Name) then 184 | begin 185 | LAsVar := LPair.Value.AsVariant; 186 | Dest := TVarData(LAsVar); 187 | 188 | Exit(True); 189 | end; 190 | end; 191 | 192 | { Key not found, means error } 193 | Clear(Dest); 194 | Result := False; 195 | end; 196 | 197 | var 198 | { Our singleton that manages our variant type } 199 | FViewDictionaryVariantType: TViewDictionaryVariantType; 200 | 201 | { Member.TSelector } 202 | 203 | function Member.TSelector.GenericInvoke(AFrom: T): K; 204 | var 205 | LValue: TValue; 206 | begin 207 | LValue := TValueInvoke(AFrom); 208 | Result := LValue.AsType(); 209 | end; 210 | 211 | { Member.TRecordFieldSelector } 212 | 213 | function Member.TRecordFieldSelector.TValueInvoke(AFrom: Pointer): TValue; 214 | begin 215 | ASSERT(Assigned(FMember)); 216 | ASSERT(FMember is TRttiField); 217 | 218 | Result := TRttiField(FMember).GetValue(AFrom); 219 | end; 220 | 221 | { Member.TClassFieldSelector } 222 | 223 | function Member.TClassFieldSelector.TValueInvoke(AFrom: TObject): TValue; 224 | begin 225 | ASSERT(Assigned(FMember)); 226 | ASSERT(FMember is TRttiField); 227 | 228 | Result := TRttiField(FMember).GetValue(AFrom); 229 | end; 230 | 231 | { Member.TClassPropertySelector } 232 | 233 | function Member.TClassPropertySelector.TValueInvoke(AFrom: TObject): TValue; 234 | begin 235 | ASSERT(Assigned(FMember)); 236 | ASSERT(FMember is TRttiProperty); 237 | 238 | Result := TRttiProperty(FMember).GetValue(AFrom); 239 | end; 240 | 241 | { Member.TViewSelector } 242 | 243 | function Member.TViewSelector.Invoke(AFrom: T): TView; 244 | var 245 | I, L: NativeInt; 246 | LCalc: TViewArray; 247 | begin 248 | { Initialize a view } 249 | VarClear(Result); 250 | 251 | L := Length(FFuncs); 252 | SetLength(LCalc, L); 253 | 254 | { Copy selected fields over } 255 | for I := 0 to Length(FFuncs) - 1 do 256 | begin 257 | LCalc[I].Key := FNames[I]; 258 | LCalc[I].Value := FFuncs[I](AFrom); 259 | end; 260 | 261 | { Give the result to the guy standing on the chair ... } 262 | with TVarData(Result) do 263 | begin 264 | VType := Member.FViewVariantType; 265 | Member.TViewArray(VPointer) := LCalc; 266 | end; 267 | end; 268 | 269 | { Member } 270 | 271 | class function Member.Name(const AName: string): TFunc; 272 | var 273 | LT, LK: PTypeInfo; 274 | LContext: TRttiContext; 275 | LType: TRttiType; 276 | LMember: TRttiMember; 277 | LSelector: TSelector; 278 | begin 279 | Result := nil; 280 | 281 | { Get the type } 282 | LT := TypeInfo(T); 283 | LK := TypeInfo(K); 284 | 285 | LType := LContext.GetType(LT); 286 | 287 | { Check for correctness } 288 | if not Assigned(LType) or not (LType.TypeKind in [tkClass, tkRecord]) then 289 | Exit; 290 | 291 | if LType.TypeKind = tkRecord then 292 | begin 293 | LMember := LType.GetField(AName); 294 | 295 | if not Assigned(LMember) then 296 | Exit; 297 | 298 | LSelector := TSelector(TRecordFieldSelector.Create()); 299 | end else 300 | if LType.TypeKind = tkClass then 301 | begin 302 | LMember := LType.GetField(AName); 303 | 304 | if Assigned(LMember) then 305 | LSelector := TSelector(TClassFieldSelector.Create()) 306 | else begin 307 | LMember := LType.GetProperty(AName); 308 | 309 | if not Assigned(LMember) then 310 | Exit; 311 | 312 | LSelector := TSelector(TClassPropertySelector.Create()); 313 | end; 314 | end; 315 | 316 | { Upload selector } 317 | LSelector.FContext := LContext; 318 | LSelector.FType := LType; 319 | LSelector.FMember := LMember; 320 | 321 | Result := LSelector; 322 | end; 323 | 324 | class function Member.Name(const AName: string): TFunc; 325 | begin 326 | Result := Member.Name(AName); 327 | end; 328 | 329 | class function Member.Name(const ANames: array of string): TFunc; 330 | var 331 | LSelector: TViewSelector; 332 | I, L: NativeInt; 333 | begin 334 | Result := nil; 335 | L := Length(ANames); 336 | 337 | if L = 0 then 338 | Exit; 339 | 340 | LSelector := TViewSelector.Create; 341 | 342 | { Prepare the array of selectors } 343 | SetLength(LSelector.FNames, L); 344 | SetLength(LSelector.FFuncs, L); 345 | 346 | { Create the array } 347 | for I := 0 to L - 1 do 348 | begin 349 | LSelector.FNames[I] := AnsiUpperCase(ANames[I]); 350 | LSelector.FFuncs[I] := Member.Name(ANames[I]); 351 | 352 | if not Assigned(LSelector.FFuncs[I]) then 353 | begin 354 | LSelector.Free; 355 | Exit; 356 | end; 357 | end; 358 | 359 | Result := LSelector; 360 | end; 361 | 362 | initialization 363 | { Register our custom variant type } 364 | FViewDictionaryVariantType := TViewDictionaryVariantType.Create(); 365 | Member.FViewVariantType := FViewDictionaryVariantType.VarType; 366 | 367 | finalization 368 | { Uregister our custom variant } 369 | FreeAndNil(FViewDictionaryVariantType); 370 | {$ELSE} 371 | implementation 372 | {$IFEND} 373 | end. 374 | -------------------------------------------------------------------------------- /src/Library/Collections.dpk: -------------------------------------------------------------------------------- 1 | package Collections; 2 | 3 | {$R *.res} 4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 5 | {$ALIGN 8} 6 | {$ASSERTIONS ON} 7 | {$BOOLEVAL OFF} 8 | {$DEBUGINFO ON} 9 | {$EXTENDEDSYNTAX ON} 10 | {$IMPORTEDDATA ON} 11 | {$IOCHECKS ON} 12 | {$LOCALSYMBOLS ON} 13 | {$LONGSTRINGS ON} 14 | {$OPENSTRINGS ON} 15 | {$OPTIMIZATION ON} 16 | {$OVERFLOWCHECKS OFF} 17 | {$RANGECHECKS OFF} 18 | {$REFERENCEINFO ON} 19 | {$SAFEDIVIDE OFF} 20 | {$STACKFRAMES OFF} 21 | {$TYPEDADDRESS OFF} 22 | {$VARSTRINGCHECKS ON} 23 | {$WRITEABLECONST OFF} 24 | {$MINENUMSIZE 1} 25 | {$IMAGEBASE $400000} 26 | {$DEFINE DEBUG} 27 | {$ENDIF IMPLICITBUILDING} 28 | {$IMPLICITBUILD ON} 29 | 30 | requires 31 | rtl; 32 | 33 | contains 34 | Collections.Bags in 'Collections.Bags.pas', 35 | Collections.Base in 'Collections.Base.pas', 36 | Collections.BidiDictionaries in 'Collections.BidiDictionaries.pas', 37 | Collections.BidiMaps in 'Collections.BidiMaps.pas', 38 | Collections.Dictionaries in 'Collections.Dictionaries.pas', 39 | Collections.Dynamic in 'Collections.Dynamic.pas', 40 | Collections.Lists in 'Collections.Lists.pas', 41 | Collections.MultiMaps in 'Collections.MultiMaps.pas', 42 | Collections.Queues in 'Collections.Queues.pas', 43 | Collections.Sets in 'Collections.Sets.pas', 44 | Collections.Stacks in 'Collections.Stacks.pas', 45 | Collections.Serialization in 'Collections.Serialization.pas'; 46 | 47 | end. 48 | 49 | -------------------------------------------------------------------------------- /src/Library/Collections.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {B6403A30-71D9-4B76-8676-CFF58E93639E} 4 | Collections.dpk 5 | 13.4 6 | Debug 7 | DCC32 8 | True 9 | Package 10 | None 11 | Win32 12 | 3 13 | Win32 14 | 15 | 16 | true 17 | 18 | 19 | true 20 | Base 21 | true 22 | 23 | 24 | true 25 | Base 26 | true 27 | 28 | 29 | 177 30 | CompanyName=Alexandru Ciobanu;FileDescription=Collections Package;FileVersion=1.2.0.177;InternalName=delphi-coll;LegalCopyright=Alexandru Ciobanu;LegalTrademarks=;OriginalFilename=;ProductName=Collections Package;ProductVersion=1.2.0.0;Comments= 31 | 1033 32 | true 33 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 34 | 2 35 | true 36 | 00400000 37 | ..\..\bin\Collections.bpl 38 | true 39 | ..\..\bin 40 | ..\..\bin;$(DCC_UnitSearchPath) 41 | x86 42 | false 43 | false 44 | true 45 | ..\..\bin 46 | false 47 | ..\..\bin 48 | false 49 | false 50 | 51 | 52 | false 53 | RELEASE;$(DCC_Define) 54 | 0 55 | false 56 | 57 | 58 | DEBUG;$(DCC_Define) 59 | 60 | 61 | 62 | MainSource 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Cfg_2 79 | Base 80 | 81 | 82 | Base 83 | 84 | 85 | Cfg_1 86 | Base 87 | 88 | 89 | 90 | 91 | 92 | Delphi.Personality.12 93 | Package 94 | 95 | 96 | 97 | Collections.dpk 98 | 99 | 100 | 101 | True 102 | False 103 | 1 104 | 0 105 | 4390 106 | 9532 107 | False 108 | False 109 | False 110 | False 111 | False 112 | 1033 113 | 1252 114 | 115 | 116 | 117 | 118 | 1.0.4390.9532 119 | 120 | 121 | 122 | 123 | 124 | 1.0.0.0 125 | 126 | 127 | 128 | 129 | 130 | 131 | 12 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/Library/Collections.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/src/Library/Collections.res -------------------------------------------------------------------------------- /src/Library/Collections_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/src/Library/Collections_Icon.ico -------------------------------------------------------------------------------- /src/Samples/Joining.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | { 29 | This file has been modified from the original by Peter Johnson 30 | (@delphidabbler). For full details of modifications see the commit history of 31 | the delphidabbler/delphi-coll fork on GitHub 32 | } 33 | 34 | 35 | (* 36 | This sample shows how the join operations can be used. 37 | *) 38 | unit Joining; 39 | interface 40 | uses 41 | SysUtils, 42 | DateUtils, 43 | Generics.Defaults, 44 | Collections.Base, 45 | Collections.Dynamic, 46 | Collections.Lists; 47 | 48 | /// Runs the current sample. 49 | procedure RunSample(); 50 | 51 | implementation 52 | 53 | type 54 | { A simple TPerson record that stores some information regarding a person. } 55 | TPerson = class 56 | FFirst, FLast: string; 57 | 58 | constructor Create(const AFirst, ALast: string); 59 | end; 60 | 61 | { TPerson } 62 | 63 | constructor TPerson.Create(const AFirst, ALast: string); 64 | begin 65 | FFirst := AFirst; 66 | FLast := ALast; 67 | end; 68 | 69 | type 70 | { A simple TPet record that stores some information regarding a pet. } 71 | TPet = class 72 | FName: string; 73 | FOwner: TPerson; 74 | 75 | constructor Create(const AName: string; const AOwner: TPerson); 76 | end; 77 | 78 | { TPerson } 79 | 80 | constructor TPet.Create(const AName: string; const AOwner: TPerson); 81 | begin 82 | FName := AName; 83 | FOwner := AOwner; 84 | end; 85 | 86 | type 87 | { This type is used when selecting the joined results } 88 | TOwnedPet = record 89 | FOwnerName: String; 90 | FPetName: String; 91 | end; 92 | 93 | { This type is used when selecting the group-joined results } 94 | TOwnedPets = record 95 | FOwnerName: String; 96 | FPetNames: ISequence; 97 | end; 98 | 99 | procedure RunSample(); 100 | var 101 | LOwners: TObjectList; 102 | LPets: TObjectList; 103 | LJoined: ISequence; 104 | LOwnedPet: TOwnedPet; 105 | LGroupJoined: ISequence; 106 | LOwnedPets: TOwnedPets; 107 | LName: String; 108 | begin 109 | WriteLn; 110 | WriteLn('=============== [Joining] ============ '); 111 | WriteLn; 112 | 113 | LOwners := TObjectList.Create; 114 | LOwners.OwnsObjects := True; 115 | 116 | LOwners.Add(TPerson.Create('John', 'McNeill')); 117 | LOwners.Add(TPerson.Create('Mary', 'Moskovitz')); 118 | LOwners.Add(TPerson.Create('Ken', 'Smith')); 119 | LOwners.Add(TPerson.Create('Lidia', 'Doroftei')); 120 | LOwners.Add(TPerson.Create('Michael', 'Dooley')); 121 | LOwners.Add(TPerson.Create('Andrea', 'Lonus')); 122 | 123 | LPets := TObjectList.Create; 124 | LPets.OwnsObjects := True; 125 | 126 | LPets.Add(TPet.Create('Sparky', LOwners[0])); 127 | LPets.Add(TPet.Create('Pookey', LOwners[1])); 128 | LPets.Add(TPet.Create('Hairy', LOwners[2])); 129 | LPets.Add(TPet.Create('Skipe', LOwners[3])); 130 | LPets.Add(TPet.Create('Fluffy', LOwners[2])); 131 | LPets.Add(TPet.Create('Fatty', LOwners[5])); 132 | LPets.Add(TPet.Create('Teethy', LOwners[0])); 133 | LPets.Add(TPet.Create('Cocky', LOwners[0])); 134 | LPets.Add(TPet.Create('Minty', LOwners[5])); 135 | LPets.Add(TPet.Create('Abandony', nil)); 136 | 137 | WriteLn('Join():'); 138 | WriteLn; 139 | 140 | { Now do the join. We're using the TPerson as the actual key. } 141 | LJoined := LOwners.Op.Join(LPets, 142 | function(Arg1: TPerson): TPerson begin Result := Arg1; end, { The outer key selector } 143 | function(Arg1: TPet): TPerson begin Result := Arg1.FOwner; end, { The inner key selector } 144 | function(Arg1: TPerson; Arg2: TPet): TOwnedPet 145 | begin 146 | Result.FOwnerName := Format('%s, %s', [Arg1.FLast, Arg1.FFirst]); 147 | Result.FPetName := Arg2.FName; 148 | end { The result selector } 149 | ); 150 | 151 | for LOwnedPet in LJoined do 152 | begin 153 | WriteLn('Person ', LOwnedPet.FOwnerName, ' owns: ', LOwnedPet.FPetName); 154 | end; 155 | 156 | WriteLn; 157 | WriteLn('GroupJoin():'); 158 | WriteLn; 159 | 160 | { Now do the join. We're using the TPerson as the actual key. } 161 | LGroupJoined := LOwners.Op.GroupJoin(LPets, 162 | function(Arg1: TPerson): TPerson begin Result := Arg1; end, { The outer key selector } 163 | function(Arg1: TPet): TPerson begin Result := Arg1.FOwner; end, { The inner key selector } 164 | function(Arg1: TPerson; Arg2: ISequence): TOwnedPets 165 | begin 166 | Result.FOwnerName := Format('%s, %s', [Arg1.FLast, Arg1.FFirst]); 167 | //! COMPILER BUG. On Delphi XE the overloaded call to 168 | // Arg2.Op.Select causes a "E2035 Not enough actual parameters" 169 | // error, even though the required method overload is present in 170 | // Collections.Base.TEnexExtOps. 171 | // BUT It was noted that the IDE was flagging the overload as "Identifier 172 | // redeclared" even though the code compiled without errors. 173 | // The solution for now is to use one of the other overloads to the Select 174 | // method that requires a second TRules argument. The value chosen 175 | // replicates exactly the functionality of the original single parameter 176 | // method 177 | (* 178 | Result.FPetNames := Arg2.Op.Select( 179 | function(Arg1: TPet): String begin Result := Arg1.FName; end); 180 | *) 181 | Result.FPetNames := Arg2.Op.Select( 182 | function(Arg1: TPet): String begin Result := Arg1.FName; end, 183 | TRules.Default 184 | ); 185 | end { The result selector } 186 | ); 187 | 188 | for LOwnedPets in LGroupJoined do 189 | begin 190 | WriteLn('Person ', LOwnedPets.FOwnerName, ' owns: '); 191 | Write(' '); 192 | 193 | for LName in LOwnedPets.FPetNames do 194 | Write(LName, ', '); 195 | 196 | WriteLn; 197 | end; 198 | 199 | LOwners.Free; 200 | LPets.Free; 201 | end; 202 | 203 | end. 204 | -------------------------------------------------------------------------------- /src/Samples/List_Store_Load.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | (* 29 | This sample shows a simple case of using the serialization module to first store then load a list from 30 | a memory stream. 31 | *) 32 | unit List_Store_Load; 33 | interface 34 | uses 35 | SysUtils, 36 | Classes, 37 | Collections.Base, 38 | Collections.Lists, 39 | Collections.Serialization; 40 | 41 | /// Runs the current sample. 42 | procedure RunSample(); 43 | 44 | { BIG NOTE: A generic type needs to be specialized in the interface section otherwise the RTTI information 45 | cannot be obtained at deserialization time and the actual type of the object reference is used. This means that 46 | if I serialize a X: TCollection -- that is actually a TList, at deserialization a new TList will be 47 | assembled only if the deserializer can find this type; otherwise the deserializer tries to assemble what it knows -- a TCollection. In 48 | most cases you will get a serialization error message ... 49 | 50 | The following declaration is required for generic types ... } 51 | type 52 | TStringList = TList; 53 | 54 | implementation 55 | 56 | 57 | procedure RunSample(); 58 | var 59 | LList: TStringList; 60 | LSerializer: TSerializer; 61 | LDeserializer: TDeserializer; 62 | LStream: TStream; 63 | LWord: string; 64 | begin 65 | WriteLn; 66 | WriteLn('=============== [List_Store_Load] ============ '); 67 | WriteLn; 68 | 69 | { Create a list filled in with some strings } 70 | LList := TStringList.Create(); 71 | LList.Add('There'); 72 | LList.Add('is'); 73 | LList.Add('cow'); 74 | LList.Add('eating'); 75 | LList.Add('grass'); 76 | LList.Add('on'); 77 | LList.Add('the'); 78 | LList.Add('field'); 79 | LList.Add(''); 80 | LList.Add('.'); 81 | 82 | { Create the stream we are going to write to } 83 | LStream := TMemoryStream.Create(); 84 | 85 | { Obtain a new default serializer } 86 | LSerializer := TSerializer.Default(LStream); 87 | try 88 | { Because the list does store its full capacity it makes sense to first call the Shrink() method to 89 | remove that extra baggage from the stream. I will not call it because I am lazy! } 90 | LSerializer.Serialize(LList); 91 | except 92 | on E: Exception do 93 | WriteLn('Serialization of our string list failed with message "', E.Message, '"'); 94 | end; 95 | LSerializer.Free; 96 | 97 | { Free the list } 98 | LStream.Seek(0, soFromBeginning); 99 | FreeAndNil(LList); 100 | 101 | { Now try to de-serialize from that stream. Obtain a de-serializer. } 102 | LDeserializer := TDeserializer.Default(LStream); 103 | try 104 | LList := LDeserializer.Deserialize() as TStringList; 105 | except 106 | on E: Exception do 107 | WriteLn('Deserialization of our string list failed with message "', E.Message, '"'); 108 | end; 109 | LDeserializer.Free; 110 | LStream.Free; 111 | 112 | if Assigned(LList) then 113 | begin 114 | for LWord in LList do 115 | Write(LWord, ' '); 116 | 117 | LList.Free; 118 | end; 119 | end; 120 | 121 | end. 122 | -------------------------------------------------------------------------------- /src/Samples/Op_Select_View.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | (* 29 | This sample shows how you can select only parts of objects or records by the means of a view. 30 | *) 31 | unit Op_Select_View; 32 | interface 33 | uses 34 | SysUtils, 35 | DateUtils, 36 | Collections.Base, 37 | Collections.Dynamic, 38 | Collections.Lists; 39 | 40 | /// Runs the current sample. 41 | procedure RunSample(); 42 | 43 | implementation 44 | 45 | type 46 | { A simple TPerson record that stores some information regarding a person. 47 | We will create a list of persons and then select only a few fields off each person. } 48 | TPerson = record 49 | FFirst, FLast: string; 50 | FAge: Integer; 51 | FBirthDate: TDate; 52 | FBirthLocation: string; 53 | 54 | constructor Create(const AFirst, ALast: string; 55 | const ABirthDate: TDate; const ABirthLocation: string); 56 | end; 57 | 58 | { TPerson } 59 | 60 | constructor TPerson.Create(const AFirst, ALast: string; const ABirthDate: TDate; const ABirthLocation: string); 61 | begin 62 | FFirst := AFirst; 63 | FLast := ALast; 64 | FBirthDate := ABirthDate; 65 | FBirthLocation := ABirthLocation; 66 | 67 | { Calculate the age from the birth date } 68 | FAge := YearsBetween(FBirthDate, Now); 69 | end; 70 | 71 | procedure RunSample(); 72 | var 73 | LPersList: TList; 74 | LView: TView; 75 | LOldest: TDate; 76 | begin 77 | WriteLn; 78 | WriteLn('=============== [Op_Select_View] ============ '); 79 | WriteLn; 80 | 81 | { Create a list of persons } 82 | LPersList := TList.Create(); 83 | 84 | { Add a few people } 85 | LPersList.Add(TPerson.Create('John', 'McNeill', EncodeDate(1984, 1, 4), 'USA')); 86 | LPersList.Add(TPerson.Create('Mary', 'Moskovitz', EncodeDate(1955, 4, 11), 'Ireland')); 87 | LPersList.Add(TPerson.Create('Ken', 'Smith', EncodeDate(2001, 8, 23), 'England')); 88 | LPersList.Add(TPerson.Create('Lidia', 'Doroftei', EncodeDate(1978, 3, 10), 'Slovakia')); 89 | 90 | { OK! Now we want to select people that are over 20 years old. And we don't need the whole structure 91 | but simply their first and last names. } 92 | 93 | WriteLn('People over 20 years old are: '); 94 | for LView in LPersList.Where( 95 | function(P: TPerson): Boolean begin Exit(P.FAge > 20) end). 96 | Op.Select(['FFirst', 'FLast']) do 97 | begin 98 | { LView is of TView type which is a variant type. It allows dynamic property resolution. 99 | Each field that we have selected in Select pops up as a property in LView. } 100 | WriteLn(' ', LView.FFirst, ' ', LView.FLast); 101 | end; 102 | 103 | WriteLn; 104 | 105 | { We can only select just one field. This is a bit more optimized since it does not create a custom variant. 106 | First approach, select using strong typing. This example will select just the birth dates from all the people and 107 | will get the biggest one. } 108 | LOldest := LPersList.Op.Select('FBirthDate').Min(); 109 | WriteLn('The oldest person in the group is born on ', DateToStr(LOldest)); 110 | 111 | { The second selection approach will not require you to give a type of the field but will instead return 112 | RTTI.TValues which you can convert to whatever you like. } 113 | 114 | { Kill the collection } 115 | LPersList.Free; 116 | end; 117 | 118 | 119 | end. 120 | -------------------------------------------------------------------------------- /src/Samples/Samples.dpr: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | program Samples; 29 | {$APPTYPE CONSOLE} 30 | 31 | uses 32 | SysUtils, 33 | Collections.Dynamic, 34 | Op_Select_View in 'Op_Select_View.pas', 35 | SplitStringEnumerable in 'SplitStringEnumerable.pas', 36 | List_Store_Load in 'List_Store_Load.pas', 37 | Sort_Person in 'Sort_Person.pas', 38 | Joining in 'Joining.pas'; 39 | 40 | begin 41 | { Just to test that we do not have memory leaks } 42 | ReportMemoryLeaksOnShutdown := True; 43 | 44 | try 45 | { Run all the samples provided in our project } 46 | Op_Select_View.RunSample(); 47 | SplitStringEnumerable.RunSample(); 48 | List_Store_Load.RunSample(); 49 | Sort_Person.RunSample(); 50 | Joining.RunSample(); 51 | 52 | except 53 | on E: Exception do 54 | Writeln(E.ClassName, ': ', E.Message); 55 | end; 56 | 57 | ReadLn; 58 | end. 59 | -------------------------------------------------------------------------------- /src/Samples/Samples.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {CB6F7C13-6F44-4B1A-8801-F9F1170AB136} 4 | 13.4 5 | Samples.dpr 6 | True 7 | Debug 8 | Console 9 | None 10 | DCC32 11 | Win32 12 | 3 13 | Win32 14 | 15 | 16 | true 17 | 18 | 19 | true 20 | Base 21 | true 22 | 23 | 24 | true 25 | Base 26 | true 27 | 28 | 29 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 30 | CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= 31 | 1048 32 | ..\..\bin;$(DCC_UnitSearchPath) 33 | ..\..\bin 34 | ..\..\bin 35 | ..\..\bin\Samples.exe 36 | 00400000 37 | ..\..\bin 38 | x86 39 | ..\..\bin 40 | 41 | 42 | false 43 | RELEASE;$(DCC_Define) 44 | 0 45 | false 46 | 47 | 48 | ..\..\bin\%Config%\Samples.exe 49 | ..\..\bin\$(Config);$(DCC_UnitSearchPath) 50 | ..\..\bin\$(Config) 51 | ..\..\bin\$(Config) 52 | ..\..\bin\$(Config) 53 | ..\..\bin\$(Config) 54 | DEBUG;$(DCC_Define) 55 | false 56 | true 57 | 58 | 59 | 60 | MainSource 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Cfg_2 69 | Base 70 | 71 | 72 | Base 73 | 74 | 75 | Cfg_1 76 | Base 77 | 78 | 79 | 80 | 81 | 82 | Delphi.Personality.12 83 | 84 | 85 | 86 | 87 | False 88 | False 89 | 1 90 | 0 91 | 0 92 | 0 93 | False 94 | False 95 | False 96 | False 97 | False 98 | 1048 99 | 1250 100 | 101 | 102 | 103 | 104 | 1.0.0.0 105 | 106 | 107 | 108 | 109 | 110 | 1.0.0.0 111 | 112 | 113 | 114 | 115 | Samples.dpr 116 | 117 | 118 | 119 | 120 | True 121 | 122 | 123 | 12 124 | 125 | 126 | -------------------------------------------------------------------------------- /src/Samples/Samples.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/src/Samples/Samples.res -------------------------------------------------------------------------------- /src/Samples/Sort_Person.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | (* 29 | This sample shows how you can sort a list of custome objects 30 | *) 31 | unit Sort_Person; 32 | interface 33 | uses 34 | SysUtils, 35 | DateUtils, 36 | Generics.Defaults, 37 | Collections.Base, 38 | Collections.Dynamic, 39 | Collections.Lists; 40 | 41 | /// Runs the current sample. 42 | procedure RunSample(); 43 | 44 | implementation 45 | 46 | type 47 | { A simple TPerson record that stores some information regarding a person. 48 | We will create a list of persons and then select only a few fields off each person. } 49 | TPerson = class 50 | FFirst, FLast: string; 51 | FAge: Integer; 52 | FBirthDate: TDate; 53 | FBirthLocation: string; 54 | 55 | constructor Create(const AFirst, ALast: string; 56 | const ABirthDate: TDate; const ABirthLocation: string); 57 | end; 58 | 59 | { TPerson } 60 | 61 | constructor TPerson.Create(const AFirst, ALast: string; const ABirthDate: TDate; const ABirthLocation: string); 62 | begin 63 | FFirst := AFirst; 64 | FLast := ALast; 65 | FBirthDate := ABirthDate; 66 | FBirthLocation := ABirthLocation; 67 | 68 | { Calculate the age from the birth date } 69 | FAge := YearsBetween(FBirthDate, Now); 70 | end; 71 | 72 | 73 | procedure RunSample(); 74 | var 75 | LList: TObjectList; 76 | LPerson: TPerson; 77 | begin 78 | WriteLn; 79 | WriteLn('=============== [Sort_Person] ============ '); 80 | WriteLn; 81 | 82 | LList := TObjectList.Create; 83 | try 84 | LList.OwnsObjects := True; 85 | 86 | { Add a few people } 87 | LList.Add(TPerson.Create('John', 'McNeill', EncodeDate(1984, 1, 4), 'USA')); 88 | LList.Add(TPerson.Create('Mary', 'Moskovitz', EncodeDate(1955, 4, 11), 'Ireland')); 89 | LList.Add(TPerson.Create('Ken', 'Smith', EncodeDate(2001, 8, 23), 'England')); 90 | LList.Add(TPerson.Create('Lidia', 'Doroftei', EncodeDate(1978, 3, 10), 'Slovakia')); 91 | 92 | { Do a normal sort based on the names } 93 | LList.Sort(TComparison( 94 | function(const ALeft, ARight: TPerson): Integer 95 | begin 96 | Result := CompareText(ALeft.FLast, ALeft.FLast); 97 | end)); 98 | 99 | for LPerson in LList do 100 | begin 101 | WriteLn(LPerson.FFirst + ' ' + LPerson.FLast + ' (' + IntToStr(LPerson.FAge) + ')'); 102 | end; 103 | 104 | WriteLn; 105 | WriteLn; 106 | WriteLn('OrdeBy:'); 107 | WriteLn; 108 | 109 | { Now try somethign new and order by } 110 | for LPerson in LList.Op.OrderBy 111 | (function (Arg1: TPerson): Integer begin Result := Arg1.FAge; end) 112 | do 113 | begin 114 | Writeln(LPerson.FFirst + ' ' + LPerson.FLast + ' (' + IntToStr(LPerson.FAge) + ')'); 115 | end; 116 | 117 | finally 118 | LList.Free; 119 | end; 120 | end; 121 | 122 | end. 123 | -------------------------------------------------------------------------------- /src/Samples/SplitStringEnumerable.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | (* 29 | This sample implements a new "collection" based on an input string split by a given character. 30 | Each element of this "pseudo-collection" is a split part of the string. 31 | 32 | NOTE: This collection is "read-only". We don't implement any higher level interfaces such as IList. This means 33 | that we don't need an internal versioning scheme and don't need to fear of thread safety issues. 34 | *) 35 | unit SplitStringEnumerable; 36 | interface 37 | uses 38 | SysUtils, 39 | Collections.Base; 40 | 41 | type 42 | { A new collection. Derive it from TEnexCollection. Since the elements in our new collection 43 | are strings (parts of a given initial string) we need to type the generic base as TEnexCollection.} 44 | TSplitStringCollection = class(TSequence) 45 | private type 46 | { 47 | This is the enumerator. It's a private type in TSplitStringCollection. Noone but this collection 48 | can instantiate it for ... safety reasons: usually the state is specific and only the collection code 49 | might be aware of that. 50 | 51 | We derive it from TEnumerator. This type implements IEnumerator and provides some base plumbing code. 52 | } 53 | TEnumerator = class(TAbstractEnumerator) 54 | private 55 | LNowIndex, LPrevIndex, FLength: NativeInt; 56 | 57 | public 58 | { The contructor. The collection will pass itself here. The enumerator needs to know who is it talking to. } 59 | constructor Create(const AOwner: TSplitStringCollection); 60 | 61 | { This method is called prior to anything else. We must return TRUE if the element was obtained, and store that element 62 | somewhere that GetCurrent can obtain. } 63 | function TryMoveNext(out ACurrent: string): Boolean; override; 64 | end; 65 | 66 | private 67 | FInputString: string; 68 | FSeparator: Char; 69 | FCount: NativeInt; 70 | 71 | protected 72 | { Now this is tricky. This function is used by all other function and users to check the length 73 | of the output collection. We don't know ahead of time ... So we will probably calculate the number of times the separator 74 | is present in the input string and store that as the count. 75 | 76 | Note that we have overridden thsi method. The deafult implemenation in TEnexCollection will request an enumerator and start 77 | enumerating till the end of the collection (thus generating the count) -- not very optimal! 78 | } 79 | function GetCount(): NativeInt; override; 80 | 81 | public 82 | { The first constructor is pretty obvious -- requires a string to be split and a character to split by. } 83 | constructor Create(const AString: string; const ASeparator: Char = ' '); overload; 84 | 85 | { The second contructor also requires a set of comparison rules (the comparer and equality comparer). These rules will be needed for 86 | Extended operations such as Max() or Min(). The inherited code from TEnexCollection expects us to provide a rules set so we ask the user 87 | if he has something specific. The first constructor will simply call this cionstructor but request the default rules set (TRules.Default). } 88 | constructor Create(const ARules: TRules; const AString: string; const ASeparator: Char = ' '); overload; 89 | 90 | { This method will simply check the count to be greater than zero ... that's it. But we need to override it to ensure we have an optimized 91 | "check for emptiness". Other Enex code will call this method and we can't afford to let the default implementation (it's slow too!). } 92 | function Empty(): Boolean; override; 93 | 94 | { Even though TEnexCollection provides a Count proprty that calls GetCount() it's better to map to a field if we have one for 95 | performance reasons. 96 | } 97 | property Count: NativeInt read FCount; 98 | 99 | { This is THE MOST IMPORTANT thing you need to provide in your collection. Even GetCount() and Empty() have default implementations in TEnexCollection. 100 | All those implementations rely on the fact that they extract an enumerator and start playing with it. SO WE ABSOLUTELY MUST provide it ... It's defined as 101 | abstract anyway so you can't avoid it. 102 | } 103 | function GetEnumerator(): IEnumerator; override; 104 | end; 105 | 106 | { This is the "facade" function. It takes a string and a separator and returns an interface 107 | reference to a new TSplitStringCollection class that you can play with. } 108 | function SplitString(const AString: string; const ASeparator: Char = ' '): ISequence; 109 | 110 | /// Runs the current sample. 111 | procedure RunSample(); 112 | 113 | implementation 114 | 115 | procedure RunSample(); 116 | var 117 | LWord, LInput: string; 118 | LGroup: IGrouping; 119 | begin 120 | WriteLn; 121 | WriteLn('=============== [SplitStringEnumerable] ============ '); 122 | WriteLn; 123 | 124 | { Assign some dummy text } 125 | LInput := 'Johnny had a bad taste in women!'; 126 | 127 | { And now let's enjoy the split action. We will split using the default SPACE character effectively 128 | getting each word. } 129 | WriteLn('Splitting "', LInput ,'": '); 130 | for LWord in SplitString(LInput) do 131 | WriteLn(' # ', LWord); 132 | 133 | WriteLn; 134 | 135 | { And now we will group all words in the string by length. Note that we have 3 "operations involved": 136 | 1. SplitString(LInput) itself which creates the input enumerable. 137 | 2. Op.GroupBy(selector) which groups all elements in the input collection by a given "rule". 138 | In current case the rule is the length of the string. This means that the output of this 139 | operation is a collection of collections. 140 | 3. Ordered(comparison) which compares a given group to another. This will sort the output in length asceding order. 141 | } 142 | WriteLn('Write all words groupped by their length:'); 143 | for LGroup in SplitString(LInput). 144 | Op.GroupBy(function(S: String): Integer begin Exit(Length(S)) end). 145 | Ordered(function(const L, R: IGrouping): Integer begin Exit(L.Key - R.Key) end) do 146 | begin 147 | { Write the group key (the length) } 148 | Write(' # ', LGroup.Key, ' characters: '); 149 | 150 | { Now iterate all the words groupped by this length and write them to the console. } 151 | for LWord in LGroup do 152 | Write(LWord, ' '); 153 | 154 | { Add a new line for the next group. } 155 | WriteLn; 156 | end; 157 | end; 158 | 159 | function SplitString(const AString: string; const ASeparator: Char): ISequence; 160 | begin 161 | { The code is absolutely stupid } 162 | Result := TSplitStringCollection.Create(AString, ASeparator); 163 | end; 164 | 165 | { TSplitStringCollection } 166 | 167 | constructor TSplitStringCollection.Create(const AString: string; const ASeparator: Char); 168 | begin 169 | { Call the more general constructor. Pass a default rule set along ... } 170 | Create(TRules.Default, AString, ASeparator); 171 | end; 172 | 173 | constructor TSplitStringCollection.Create(const ARules: TRules; const AString: string; const ASeparator: Char); 174 | var 175 | LChar: Char; 176 | begin 177 | { This is the core constructor. Step 1 is to call the inherited constructor ans pass the rule set to it. 178 | It will prepare the collection basics. } 179 | inherited Create(ARules); 180 | 181 | { The next step is to store the variables } 182 | FInputString := AString; 183 | FSeparator := ASeparator; 184 | 185 | { Now we need to check how many split points we will have } 186 | 187 | if Length(AString) > 0 then 188 | begin 189 | FCount := 1; 190 | 191 | for LChar in AString do 192 | if LChar = ASeparator then 193 | Inc(FCount); 194 | 195 | { Well, that was simple :) } 196 | end; 197 | end; 198 | 199 | function TSplitStringCollection.Empty: Boolean; 200 | begin 201 | { As promised ... simply check that FCount is bigger than zero } 202 | Result := FCount > 0; 203 | end; 204 | 205 | function TSplitStringCollection.GetCount: NativeInt; 206 | begin 207 | { Just return the count } 208 | Result := FCount; 209 | end; 210 | 211 | function TSplitStringCollection.GetEnumerator: IEnumerator; 212 | begin 213 | { Create an enumerator instance and return it as an interface reference. } 214 | Result := TEnumerator.Create(Self); 215 | end; 216 | 217 | { TSplitStringCollection.TEnumerator } 218 | 219 | constructor TSplitStringCollection.TEnumerator.Create(const AOwner: TSplitStringCollection); 220 | begin 221 | { Store reference to our collection! } 222 | inherited Create(AOwner); 223 | 224 | { Initialize indexes. } 225 | LPrevIndex := 1; 226 | LNowIndex := 1; 227 | 228 | { This if to minimize length calls } 229 | FLength := Length(AOwner.FInputString); 230 | end; 231 | 232 | function TSplitStringCollection.TEnumerator.TryMoveNext(out ACurrent: string): Boolean; 233 | var 234 | LOwner: TSplitStringCollection; 235 | begin 236 | { Store a strong type to our owner collection. "Owner" is a property exposed by the base enumerator } 237 | LOwner := TSplitStringCollection(Owner); 238 | 239 | { This is the function that will actually do the work! Wow, we have written so much 240 | in simple preparation. The code in this method will actually split the string: } 241 | 242 | { Start with a "we are at the end of the world" attitude. } 243 | Result := false; 244 | 245 | while LNowIndex <= FLength do 246 | begin 247 | { Check if the current character is a separator } 248 | if LOwner.FInputString[LNowIndex] = LOwner.FSeparator then 249 | begin 250 | { Yes, we will cut over the required part and place it for the taking } 251 | ACurrent := System.Copy(LOwner.FInputString, LPrevIndex, (LNowIndex - LPrevIndex)); 252 | 253 | { Adjust previous idex so we know where to cut from. } 254 | LPrevIndex := LNowIndex + 1; 255 | 256 | { We have found the next piece. We might as well just break. } 257 | Result := true; 258 | end; 259 | 260 | { Increment the current index. } 261 | Inc(LNowIndex); 262 | 263 | { If we found a piece exit at this iteration } 264 | if Result then 265 | Exit; 266 | end; 267 | 268 | { Special case! We got here so there is a last split available } 269 | if LPrevIndex < LNowIndex then 270 | begin 271 | { Copy the last peice and mark the result as OK. } 272 | ACurrent := Copy(LOwner.FInputString, LPrevIndex, FLength - LPrevIndex + 1); 273 | LPrevIndex := LNowIndex + 1; 274 | 275 | Result := true; 276 | end; 277 | end; 278 | 279 | end. 280 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.Bags.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | unit Tests.Conformance.Bags; 29 | interface 30 | uses SysUtils, 31 | Tests.Conformance.Base, 32 | TestFramework, 33 | Generics.Collections, 34 | Collections.Base, 35 | Collections.Bags; 36 | 37 | type 38 | TConformance_TBag = class(TConformance_IBag) 39 | protected 40 | procedure SetUp_IBag(out AEmpty, AOne, AFull: IBag; out AElements: TElements; out AOrdering: TOrdering); override; 41 | end; 42 | 43 | TConformance_TSortedBag = class(TConformance_IBag) 44 | protected 45 | function GetSortOrder: Boolean; virtual; abstract; 46 | procedure SetUp_IBag(out AEmpty, AOne, AFull: IBag; out AElements: TElements; out AOrdering: TOrdering); override; 47 | end; 48 | 49 | TConformance_TSortedBag_Asc = class(TConformance_TSortedBag) 50 | protected 51 | function GetSortOrder: Boolean; override; 52 | end; 53 | 54 | TConformance_TSortedBag_Desc = class(TConformance_TSortedBag) 55 | protected 56 | function GetSortOrder: Boolean; override; 57 | end; 58 | 59 | implementation 60 | 61 | { TConformance_TBag } 62 | 63 | procedure TConformance_TBag.SetUp_IBag(out AEmpty, AOne, AFull: IBag; 64 | out AElements: TElements; out AOrdering: TOrdering); 65 | var 66 | LItem: NativeInt; 67 | LEmpty, LOne, LFull: TBag; 68 | begin 69 | AElements := GenerateRepeatableRandomElements(); 70 | AOrdering := oNone; 71 | 72 | LEmpty := TBag.Create(); LEmpty.RemoveNotification := RemoveNotification; 73 | LOne := TBag.Create(); LOne.RemoveNotification := RemoveNotification; 74 | LOne.Add(AElements[0]); 75 | LFull := TBag.Create(); LFull.RemoveNotification := RemoveNotification; 76 | 77 | for LItem in AElements do 78 | LFull.Add(LItem); 79 | 80 | AEmpty := LEmpty; 81 | AOne := LOne; 82 | AFull := LFull; 83 | end; 84 | 85 | { TConformance_TSortedBag } 86 | 87 | procedure TConformance_TSortedBag.SetUp_IBag(out AEmpty, AOne, 88 | AFull: IBag; out AElements: TElements; out AOrdering: TOrdering); 89 | var 90 | LItem: NativeInt; 91 | LEmpty, LOne, LFull: TSortedBag; 92 | begin 93 | AElements := GenerateRepeatableRandomElements(); 94 | 95 | if GetSortOrder then 96 | AOrdering := oAscending 97 | else 98 | AOrdering := oDescending; 99 | 100 | LEmpty := TSortedBag.Create(TRules.Default, GetSortOrder); LEmpty.RemoveNotification := RemoveNotification; 101 | LOne := TSortedBag.Create(TRules.Default, GetSortOrder); LOne.RemoveNotification := RemoveNotification; 102 | LOne.Add(AElements[0]); 103 | LFull := TSortedBag.Create(TRules.Default, GetSortOrder); LFull.RemoveNotification := RemoveNotification; 104 | 105 | for LItem in AElements do 106 | LFull.Add(LItem); 107 | 108 | AEmpty := LEmpty; 109 | AOne := LOne; 110 | AFull := LFull; 111 | end; 112 | 113 | { TConformance_TSortedBag_Asc } 114 | 115 | function TConformance_TSortedBag_Asc.GetSortOrder: Boolean; 116 | begin 117 | Result := True; 118 | end; 119 | 120 | { TConformance_TSortedBag_Desc } 121 | 122 | function TConformance_TSortedBag_Desc.GetSortOrder: Boolean; 123 | begin 124 | Result := False; 125 | end; 126 | 127 | initialization 128 | RegisterTests('Conformance.Simple.Bags', [ 129 | TConformance_TBag.Suite, 130 | TConformance_TSortedBag_Asc.Suite, 131 | TConformance_TSortedBag_Desc.Suite 132 | ]); 133 | end. 134 | 135 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.BidiDictionaries.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | { 29 | This file has been modified from the original by Peter Johnson 30 | (@delphidabbler). For full details of modifications see the commit history of 31 | the delphidabbler/delphi-coll fork on GitHub 32 | } 33 | 34 | 35 | unit Tests.Conformance.BidiDictionaries; 36 | interface 37 | uses SysUtils, 38 | Tests.Conformance.Base, 39 | TestFramework, 40 | Generics.Collections, 41 | Collections.Base, 42 | Collections.BidiDictionaries; 43 | 44 | type 45 | // TODO: Implement this test class 46 | TConformance_TBidiDictionary = class(TConformance_IBidiDictionary) 47 | protected 48 | procedure SetUp_IBidiDictionary(out AEmpty, AOne, AFull: IBidiDictionary; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 49 | published 50 | end; 51 | 52 | // TODO: Implement this test class 53 | TConformance_TSortedBidiDictionary = class(TConformance_IBidiDictionary) 54 | protected 55 | procedure SetUp_IBidiDictionary(out AEmpty, AOne, AFull: IBidiDictionary; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 56 | published 57 | end; 58 | 59 | // TODO: Implement this test class 60 | TConformance_TDoubleSortedBidiDictionary = class(TConformance_IBidiDictionary) 61 | protected 62 | procedure SetUp_IBidiDictionary(out AEmpty, AOne, AFull: IBidiDictionary; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 63 | published 64 | end; 65 | 66 | type 67 | // TODO: Implement this test class 68 | TConformance_TBidiDictionary_Keys = class(TConformance_ISequence) 69 | protected 70 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 71 | published 72 | end; 73 | 74 | // TODO: Implement this test class 75 | TConformance_TBidiDictionary_Values = class(TConformance_ISequence) 76 | protected 77 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 78 | published 79 | end; 80 | 81 | // TODO: Implement this test class 82 | TConformance_TSortedBidiDictionary_Keys = class(TConformance_ISequence) 83 | protected 84 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 85 | published 86 | end; 87 | 88 | // TODO: Implement this test class 89 | TConformance_TSortedBidiDictionary_Values = class(TConformance_ISequence) 90 | protected 91 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 92 | published 93 | end; 94 | 95 | // TODO: Implement this test class 96 | TConformance_TDoubleSortedBidiDictionary_Keys = class(TConformance_ISequence) 97 | protected 98 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 99 | published 100 | end; 101 | 102 | // TODO: Implement this test class 103 | TConformance_TDoubleSortedBidiDictionary_Values = class(TConformance_ISequence) 104 | protected 105 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 106 | published 107 | end; 108 | 109 | implementation 110 | 111 | { TConformance_TBidiDictionary } 112 | 113 | procedure TConformance_TBidiDictionary.SetUp_IBidiDictionary(out AEmpty, AOne, 114 | AFull: IBidiDictionary; out APairs: TPairs; 115 | out AKeyOrdering: TOrdering); 116 | begin 117 | // TODO: Set dictionaries up correctly 118 | AEmpty := TBidiDictionary.Create; 119 | AOne := TBiDiDictionary.Create; 120 | AFull := TBiDiDictionary.Create; 121 | SetLength(APairs, 0); 122 | AKeyOrdering := oNone; 123 | end; 124 | 125 | { TConformance_TSortedBidiDictionary } 126 | 127 | procedure TConformance_TSortedBidiDictionary.SetUp_IBidiDictionary(out AEmpty, 128 | AOne, AFull: IBidiDictionary; out APairs: TPairs; 129 | out AKeyOrdering: TOrdering); 130 | begin 131 | // TODO: Set dictionaries up correctly 132 | AEmpty := TSortedBidiDictionary.Create; 133 | AOne := TSortedBiDiDictionary.Create; 134 | AFull := TSortedBiDiDictionary.Create; 135 | SetLength(APairs, 0); 136 | AKeyOrdering := oAscending; 137 | end; 138 | 139 | { TConformance_TDoubleSortedBidiDictionary } 140 | 141 | procedure TConformance_TDoubleSortedBidiDictionary.SetUp_IBidiDictionary( 142 | out AEmpty, AOne, AFull: IBidiDictionary; 143 | out APairs: TPairs; out AKeyOrdering: TOrdering); 144 | begin 145 | // TODO: Set dictionaries up correctly 146 | AEmpty := TDoubleSortedBidiDictionary.Create; 147 | AOne := TDoubleSortedBidiDictionary.Create; 148 | AFull := TDoubleSortedBidiDictionary.Create; 149 | SetLength(APairs, 0); 150 | AKeyOrdering := oAscending; 151 | end; 152 | 153 | { TConformance_TBidiDictionary_Keys } 154 | 155 | procedure TConformance_TBidiDictionary_Keys.SetUp_ISequence(out AEmpty, AOne, 156 | AFull: ISequence; out AElements: TElements; 157 | out AOrdering: TOrdering); 158 | var 159 | LDict: IBidiDictionary; 160 | begin 161 | // TODO: Set dictionaries up correctly 162 | LDict := TBidiDictionary.Create; 163 | AEmpty := LDict.Keys; 164 | AOne := LDict.Keys; 165 | AFull := LDict.Keys; 166 | SetLength(AElements, 0); 167 | AOrdering := oNone; 168 | end; 169 | 170 | { TConformance_TBidiDictionary_Values } 171 | 172 | procedure TConformance_TBidiDictionary_Values.SetUp_ISequence(out AEmpty, AOne, 173 | AFull: ISequence; out AElements: TElements; 174 | out AOrdering: TOrdering); 175 | var 176 | LDict: IBidiDictionary; 177 | begin 178 | // TODO: Set dictionaries up correctly 179 | LDict := TBidiDictionary.Create; 180 | AEmpty := LDict.Values; 181 | AOne := LDict.Values; 182 | AFull := LDict.Values; 183 | SetLength(AElements, 0); 184 | AOrdering := oNone; 185 | end; 186 | 187 | { TConformance_TSortedBidiDictionary_Keys } 188 | 189 | procedure TConformance_TSortedBidiDictionary_Keys.SetUp_ISequence(out AEmpty, 190 | AOne, AFull: ISequence; out AElements: TElements; 191 | out AOrdering: TOrdering); 192 | var 193 | LDict: IBidiDictionary; 194 | begin 195 | // TODO: Set dictionaries up correctly 196 | LDict := TSortedBidiDictionary.Create; 197 | AEmpty := LDict.Keys; 198 | AOne := LDict.Keys; 199 | AFull := LDict.Keys; 200 | SetLength(AElements, 0); 201 | AOrdering := oAscending; 202 | end; 203 | 204 | { TConformance_TSortedBidiDictionary_Values } 205 | 206 | procedure TConformance_TSortedBidiDictionary_Values.SetUp_ISequence(out AEmpty, 207 | AOne, AFull: ISequence; out AElements: TElements; 208 | out AOrdering: TOrdering); 209 | var 210 | LDict: IBidiDictionary; 211 | begin 212 | // TODO: Set dictionaries up correctly 213 | LDict := TSortedBidiDictionary.Create; 214 | AEmpty := LDict.Values; 215 | AOne := LDict.Values; 216 | AFull := LDict.Values; 217 | SetLength(AElements, 0); 218 | AOrdering := oAscending; 219 | end; 220 | 221 | { TConformance_TDoubleSortedBidiDictionary_Keys } 222 | 223 | procedure TConformance_TDoubleSortedBidiDictionary_Keys.SetUp_ISequence( 224 | out AEmpty, AOne, AFull: ISequence; out AElements: TElements; 225 | out AOrdering: TOrdering); 226 | var 227 | LDict: IBidiDictionary; 228 | begin 229 | // TODO: Set dictionaries up correctly 230 | LDict := TDoubleSortedBidiDictionary.Create; 231 | AEmpty := LDict.Keys; 232 | AOne := LDict.Keys; 233 | AFull := LDict.Keys; 234 | SetLength(AElements, 0); 235 | AOrdering := oAscending; 236 | end; 237 | 238 | { TConformance_TDoubleSortedBidiDictionary_Values } 239 | 240 | procedure TConformance_TDoubleSortedBidiDictionary_Values.SetUp_ISequence( 241 | out AEmpty, AOne, AFull: ISequence; out AElements: TElements; 242 | out AOrdering: TOrdering); 243 | var 244 | LDict: IBidiDictionary; 245 | begin 246 | // TODO: Set dictionaries up correctly 247 | LDict := TDoubleSortedBidiDictionary.Create; 248 | AEmpty := LDict.Values; 249 | AOne := LDict.Values; 250 | AFull := LDict.Values; 251 | SetLength(AElements, 0); 252 | AOrdering := oAscending; 253 | end; 254 | 255 | initialization 256 | RegisterTests('Conformance.Associative.BidiDictionaries', [ 257 | TConformance_TBidiDictionary.Suite, 258 | TConformance_TSortedBidiDictionary.Suite, 259 | TConformance_TDoubleSortedBidiDictionary.Suite 260 | ]); 261 | 262 | RegisterTests('Conformance.Simple.Selectors', [ 263 | TConformance_TBidiDictionary_Keys.Suite, 264 | TConformance_TBidiDictionary_Values.Suite, 265 | TConformance_TSortedBidiDictionary_Keys.Suite, 266 | TConformance_TSortedBidiDictionary_Values.Suite, 267 | TConformance_TDoubleSortedBidiDictionary_Keys.Suite, 268 | TConformance_TDoubleSortedBidiDictionary_Values.Suite 269 | ]); 270 | 271 | end. 272 | 273 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.BidiMaps.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | { 29 | This file has been modified from the original by Peter Johnson 30 | (@delphidabbler). For full details of modifications see the commit history of 31 | the delphidabbler/delphi-coll fork on GitHub 32 | } 33 | 34 | 35 | unit Tests.Conformance.BidiMaps; 36 | interface 37 | uses SysUtils, 38 | Tests.Conformance.Base, 39 | TestFramework, 40 | Generics.Collections, 41 | Collections.Base, 42 | Collections.BidiMaps; 43 | 44 | type 45 | // TODO: Implement this test class 46 | TConformance_TBidiMap = class(TConformance_IBidiMap) 47 | protected 48 | procedure SetUp_IBidiMap(out AEmpty, AOne, AFull: IBidiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 49 | published 50 | end; 51 | 52 | // TODO: Implement this test class 53 | TConformance_TSortedBidiMap = class(TConformance_IBidiMap) 54 | protected 55 | procedure SetUp_IBidiMap(out AEmpty, AOne, AFull: IBidiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 56 | published 57 | end; 58 | 59 | // TODO: Implement this test class 60 | TConformance_TDoubleSortedBidiMap = class(TConformance_IBidiMap) 61 | protected 62 | procedure SetUp_IBidiMap(out AEmpty, AOne, AFull: IBidiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 63 | published 64 | end; 65 | 66 | type 67 | // TODO: Implement this test class 68 | TConformance_TBidiMap_Keys = class(TConformance_ISequence) 69 | protected 70 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 71 | published 72 | end; 73 | 74 | // TODO: Implement this test class 75 | TConformance_TBidiMap_Values = class(TConformance_ISequence) 76 | protected 77 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 78 | published 79 | end; 80 | 81 | // TODO: Implement this test class 82 | TConformance_TSortedBidiMap_Keys = class(TConformance_ISequence) 83 | protected 84 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 85 | published 86 | end; 87 | 88 | // TODO: Implement this test class 89 | TConformance_TSortedBidiMap_Values = class(TConformance_ISequence) 90 | protected 91 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 92 | published 93 | end; 94 | 95 | // TODO: Implement this test class 96 | TConformance_TDoubleSortedBidiMap_Keys = class(TConformance_ISequence) 97 | protected 98 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 99 | published 100 | end; 101 | 102 | // TODO: Implement this test class 103 | TConformance_TDoubleSortedBidiMap_Values = class(TConformance_ISequence) 104 | protected 105 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 106 | published 107 | end; 108 | 109 | 110 | implementation 111 | 112 | { TConformance_TBidiMap } 113 | 114 | procedure TConformance_TBidiMap.SetUp_IBidiMap(out AEmpty, AOne, 115 | AFull: IBidiMap; out APairs: TPairs; 116 | out AKeyOrdering: TOrdering); 117 | begin 118 | // TODO: Set maps up correctly 119 | AEmpty := TBidiMap.Create; 120 | AOne := TBidiMap.Create; 121 | AFull := TBidiMap.Create; 122 | SetLength(APairs, 0); 123 | AKeyOrdering := oNone; 124 | end; 125 | 126 | { TConformance_TSortedBidiMap } 127 | 128 | procedure TConformance_TSortedBidiMap.SetUp_IBidiMap(out AEmpty, AOne, 129 | AFull: IBidiMap; out APairs: TPairs; 130 | out AKeyOrdering: TOrdering); 131 | begin 132 | // TODO: Set maps up correctly 133 | AEmpty := TSortedBidiMap.Create; 134 | AOne := TSortedBidiMap.Create; 135 | AFull := TSortedBidiMap.Create; 136 | SetLength(APairs, 0); 137 | AKeyOrdering := oAscending; 138 | end; 139 | 140 | { TConformance_TDoubleSortedBidiMap } 141 | 142 | procedure TConformance_TDoubleSortedBidiMap.SetUp_IBidiMap(out AEmpty, AOne, 143 | AFull: IBidiMap; out APairs: TPairs; 144 | out AKeyOrdering: TOrdering); 145 | begin 146 | // TODO: Set maps up correctly 147 | AEmpty := TDoubleSortedBidiMap.Create; 148 | AOne := TDoubleSortedBidiMap.Create; 149 | AFull := TDoubleSortedBidiMap.Create; 150 | SetLength(APairs, 0); 151 | AKeyOrdering := oAscending; 152 | end; 153 | 154 | { TConformance_TBidiMap_Keys } 155 | 156 | procedure TConformance_TBidiMap_Keys.SetUp_ISequence(out AEmpty, AOne, 157 | AFull: ISequence; out AElements: TElements; 158 | out AOrdering: TOrdering); 159 | var 160 | LMap: IBidiMap; 161 | begin 162 | // TODO: Set maps up correctly 163 | LMap := TBidiMap.Create; 164 | AEmpty := LMap.Keys; 165 | AOne := LMap.Keys; 166 | AFull := LMap.Keys; 167 | SetLength(AElements, 0); 168 | AOrdering := oNone; 169 | end; 170 | 171 | { TConformance_TBidiMap_Values } 172 | 173 | procedure TConformance_TBidiMap_Values.SetUp_ISequence(out AEmpty, AOne, 174 | AFull: ISequence; out AElements: TElements; 175 | out AOrdering: TOrdering); 176 | var 177 | LMap: IBidiMap; 178 | begin 179 | // TODO: Set maps up correctly 180 | LMap := TBidiMap.Create; 181 | AEmpty := LMap.Values; 182 | AOne := LMap.Values; 183 | AFull := LMap.Values; 184 | SetLength(AElements, 0); 185 | AOrdering := oNone; 186 | end; 187 | 188 | { TConformance_TSortedBidiMap_Keys } 189 | 190 | procedure TConformance_TSortedBidiMap_Keys.SetUp_ISequence(out AEmpty, AOne, 191 | AFull: ISequence; out AElements: TElements; 192 | out AOrdering: TOrdering); 193 | var 194 | LMap: IBidiMap; 195 | begin 196 | // TODO: Set maps up correctly 197 | LMap := TSortedBidiMap.Create; 198 | AEmpty := LMap.Keys; 199 | AOne := LMap.Keys; 200 | AFull := LMap.Keys; 201 | SetLength(AElements, 0); 202 | AOrdering := oAscending; 203 | end; 204 | 205 | { TConformance_TSortedBidiMap_Values } 206 | 207 | procedure TConformance_TSortedBidiMap_Values.SetUp_ISequence(out AEmpty, AOne, 208 | AFull: ISequence; out AElements: TElements; 209 | out AOrdering: TOrdering); 210 | var 211 | LMap: IBidiMap; 212 | begin 213 | // TODO: Set maps up correctly 214 | LMap := TSortedBidiMap.Create; 215 | AEmpty := LMap.Values; 216 | AOne := LMap.Values; 217 | AFull := LMap.Values; 218 | SetLength(AElements, 0); 219 | AOrdering := oAscending; 220 | end; 221 | 222 | { TConformance_TDoubleSortedBidiMap_Keys } 223 | 224 | procedure TConformance_TDoubleSortedBidiMap_Keys.SetUp_ISequence(out AEmpty, 225 | AOne, AFull: ISequence; out AElements: TElements; 226 | out AOrdering: TOrdering); 227 | var 228 | LMap: IBidiMap; 229 | begin 230 | // TODO: Set maps up correctly 231 | LMap := TDoubleSortedBidiMap.Create; 232 | AEmpty := LMap.Keys; 233 | AOne := LMap.Keys; 234 | AFull := LMap.Keys; 235 | SetLength(AElements, 0); 236 | AOrdering := oAscending; 237 | end; 238 | 239 | { TConformance_TDoubleSortedBidiMap_Values } 240 | 241 | procedure TConformance_TDoubleSortedBidiMap_Values.SetUp_ISequence(out AEmpty, 242 | AOne, AFull: ISequence; out AElements: TElements; 243 | out AOrdering: TOrdering); 244 | var 245 | LMap: IBidiMap; 246 | begin 247 | // TODO: Set maps up correctly 248 | LMap := TDoubleSortedBidiMap.Create; 249 | AEmpty := LMap.Values; 250 | AOne := LMap.Values; 251 | AFull := LMap.Values; 252 | SetLength(AElements, 0); 253 | AOrdering := oAscending; 254 | end; 255 | 256 | initialization 257 | RegisterTests('Conformance.Associative.BidiMaps', [ 258 | TConformance_TBidiMap.Suite, 259 | TConformance_TSortedBidiMap.Suite, 260 | TConformance_TDoubleSortedBidiMap.Suite 261 | ]); 262 | 263 | RegisterTests('Conformance.Simple.Selectors', [ 264 | TConformance_TBidiMap_Keys.Suite, 265 | TConformance_TBidiMap_Values.Suite, 266 | TConformance_TSortedBidiMap_Keys.Suite, 267 | TConformance_TSortedBidiMap_Values.Suite, 268 | TConformance_TDoubleSortedBidiMap_Keys.Suite, 269 | TConformance_TDoubleSortedBidiMap_Values.Suite 270 | ]); 271 | 272 | end. 273 | 274 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.Dictionaries.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | { 29 | This file has been modified from the original by Peter Johnson 30 | (@delphidabbler). For full details of modifications see the commit history of 31 | the delphidabbler/delphi-coll fork on GitHub 32 | } 33 | 34 | 35 | unit Tests.Conformance.Dictionaries; 36 | interface 37 | uses SysUtils, 38 | Tests.Conformance.Base, 39 | TestFramework, 40 | Generics.Collections, 41 | Collections.Base, 42 | Collections.Dictionaries; 43 | 44 | type 45 | // TODO: Implement this test class 46 | TConformance_TDictionary = class(TConformance_IDictionary) 47 | protected 48 | procedure SetUp_IDictionary(out AEmpty, AOne, AFull: IDictionary; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 49 | published 50 | end; 51 | 52 | // TODO: Implement this test class 53 | TConformance_TLinkedDictionary = class(TConformance_IDictionary) 54 | protected 55 | procedure SetUp_IDictionary(out AEmpty, AOne, AFull: IDictionary; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 56 | published 57 | end; 58 | 59 | // TODO: Implement this test class 60 | TConformance_TSortedDictionary = class(TConformance_IDictionary) 61 | protected 62 | procedure SetUp_IDictionary(out AEmpty, AOne, AFull: IDictionary; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 63 | published 64 | end; 65 | 66 | type 67 | // TODO: Implement this test class 68 | TConformance_TDictionary_Keys = class(TConformance_ISequence) 69 | protected 70 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 71 | published 72 | end; 73 | 74 | // TODO: Implement this test class 75 | TConformance_TDictionary_Values = class(TConformance_ISequence) 76 | protected 77 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 78 | published 79 | end; 80 | 81 | // TODO: Implement this test class 82 | TConformance_TLinkedDictionary_Keys = class(TConformance_ISequence) 83 | protected 84 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 85 | published 86 | end; 87 | 88 | // TODO: Implement this test class 89 | TConformance_TLinkedDictionary_Values = class(TConformance_ISequence) 90 | protected 91 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 92 | published 93 | end; 94 | 95 | // TODO: Implement this test class 96 | TConformance_TSortedDictionary_Keys = class(TConformance_ISequence) 97 | protected 98 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 99 | published 100 | end; 101 | 102 | // TODO: Implement this test class 103 | TConformance_TSortedDictionary_Values = class(TConformance_ISequence) 104 | protected 105 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 106 | published 107 | end; 108 | 109 | implementation 110 | 111 | { TConformance_TDictionary } 112 | 113 | procedure TConformance_TDictionary.SetUp_IDictionary(out AEmpty, AOne, 114 | AFull: IDictionary; out APairs: TPairs; 115 | out AKeyOrdering: TOrdering); 116 | begin 117 | // TODO: Set dictionaries up correctly 118 | AEmpty := TDictionary.Create; 119 | AOne := TDictionary.Create; 120 | AFull := TDictionary.Create; 121 | SetLength(APairs, 0); 122 | AKeyOrdering := oNone; 123 | end; 124 | 125 | { TConformance_TLinkedDictionary } 126 | 127 | procedure TConformance_TLinkedDictionary.SetUp_IDictionary(out AEmpty, AOne, 128 | AFull: IDictionary; out APairs: TPairs; 129 | out AKeyOrdering: TOrdering); 130 | begin 131 | // TODO: Set dictionaries up correctly 132 | AEmpty := TLinkedDictionary.Create; 133 | AOne := TLinkedDictionary.Create; 134 | AFull := TLinkedDictionary.Create; 135 | SetLength(APairs, 0); 136 | AKeyOrdering := oNone; 137 | end; 138 | 139 | { TConformance_TSortedDictionary } 140 | 141 | procedure TConformance_TSortedDictionary.SetUp_IDictionary(out AEmpty, AOne, 142 | AFull: IDictionary; out APairs: TPairs; 143 | out AKeyOrdering: TOrdering); 144 | begin 145 | // TODO: Set dictionaries up correctly 146 | AEmpty := TSortedDictionary.Create; 147 | AOne := TSortedDictionary.Create; 148 | AFull := TSortedDictionary.Create; 149 | SetLength(APairs, 0); 150 | AKeyOrdering := oAscending; 151 | end; 152 | 153 | { TConformance_TDictionary_Keys } 154 | 155 | procedure TConformance_TDictionary_Keys.SetUp_ISequence(out AEmpty, AOne, 156 | AFull: ISequence; out AElements: TElements; 157 | out AOrdering: TOrdering); 158 | var 159 | LDict: IDictionary; 160 | begin 161 | // TODO: Set dictionaries up correctly 162 | LDict := TDictionary.Create; 163 | AEmpty := LDict.Keys; 164 | AOne := LDict.Keys; 165 | AFull := LDict.Keys; 166 | SetLength(AElements, 0); 167 | end; 168 | 169 | { TConformance_TDictionary_Values } 170 | 171 | procedure TConformance_TDictionary_Values.SetUp_ISequence(out AEmpty, AOne, 172 | AFull: ISequence; out AElements: TElements; 173 | out AOrdering: TOrdering); 174 | var 175 | LDict: IDictionary; 176 | begin 177 | // TODO: Set dictionaries up correctly 178 | LDict := TDictionary.Create; 179 | AEmpty := LDict.Values; 180 | AOne := LDict.Values; 181 | AFull := LDict.Values; 182 | SetLength(AElements, 0); 183 | end; 184 | 185 | { TConformance_TLinkedDictionary_Keys } 186 | 187 | procedure TConformance_TLinkedDictionary_Keys.SetUp_ISequence(out AEmpty, AOne, 188 | AFull: ISequence; out AElements: TElements; 189 | out AOrdering: TOrdering); 190 | var 191 | LDict: IDictionary; 192 | begin 193 | // TODO: Set dictionaries up correctly 194 | LDict := TLinkedDictionary.Create; 195 | AEmpty := LDict.Keys; 196 | AOne := LDict.Keys; 197 | AFull := LDict.Keys; 198 | SetLength(AElements, 0); 199 | end; 200 | 201 | { TConformance_TLinkedDictionary_Values } 202 | 203 | procedure TConformance_TLinkedDictionary_Values.SetUp_ISequence(out AEmpty, 204 | AOne, AFull: ISequence; out AElements: TElements; 205 | out AOrdering: TOrdering); 206 | var 207 | LDict: IDictionary; 208 | begin 209 | // TODO: Set dictionaries up correctly 210 | LDict := TLinkedDictionary.Create; 211 | AEmpty := LDict.Values; 212 | AOne := LDict.Values; 213 | AFull := LDict.Values; 214 | SetLength(AElements, 0); 215 | end; 216 | 217 | { TConformance_TSortedDictionary_Keys } 218 | 219 | procedure TConformance_TSortedDictionary_Keys.SetUp_ISequence(out AEmpty, AOne, 220 | AFull: ISequence; out AElements: TElements; 221 | out AOrdering: TOrdering); 222 | var 223 | LDict: IDictionary; 224 | begin 225 | // TODO: Set dictionaries up correctly 226 | LDict := TSortedDictionary.Create; 227 | AEmpty := LDict.Keys; 228 | AOne := LDict.Keys; 229 | AFull := LDict.Keys; 230 | SetLength(AElements, 0); 231 | end; 232 | 233 | { TConformance_TSortedDictionary_Values } 234 | 235 | procedure TConformance_TSortedDictionary_Values.SetUp_ISequence(out AEmpty, 236 | AOne, AFull: ISequence; out AElements: TElements; 237 | out AOrdering: TOrdering); 238 | var 239 | LDict: IDictionary; 240 | begin 241 | // TODO: Set dictionaries up correctly 242 | LDict := TSortedDictionary.Create; 243 | AEmpty := LDict.Values; 244 | AOne := LDict.Values; 245 | AFull := LDict.Values; 246 | SetLength(AElements, 0); 247 | end; 248 | 249 | initialization 250 | RegisterTests('Conformance.Associative.Dictionaries', [ 251 | TConformance_TDictionary.Suite, 252 | TConformance_TLinkedDictionary.Suite, 253 | TConformance_TSortedDictionary.Suite 254 | ]); 255 | 256 | RegisterTests('Conformance.Simple.Selectors', [ 257 | TConformance_TDictionary_Keys.Suite, 258 | TConformance_TDictionary_Values.Suite, 259 | TConformance_TLinkedDictionary_Keys.Suite, 260 | TConformance_TLinkedDictionary_Values.Suite, 261 | TConformance_TSortedDictionary_Keys.Suite, 262 | TConformance_TSortedDictionary_Values.Suite 263 | ]); 264 | 265 | end. 266 | 267 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.Lists.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | unit Tests.Conformance.Lists; 29 | interface 30 | uses SysUtils, 31 | Tests.Conformance.Base, 32 | TestFramework, 33 | Generics.Collections, 34 | Collections.Base, 35 | Collections.Lists; 36 | 37 | type 38 | TConformance_TList = class(TConformance_IList) 39 | protected 40 | procedure SetUp_IList(out AEmpty, AOne, AFull: IList; out AElements: TElements; out AOrdering: TOrdering); override; 41 | end; 42 | 43 | TConformance_TSortedList = class(TConformance_IList) 44 | protected 45 | function GetSortOrder: Boolean; virtual; abstract; 46 | procedure SetUp_IList(out AEmpty, AOne, AFull: IList; out AElements: TElements; out AOrdering: TOrdering); override; 47 | end; 48 | 49 | TConformance_TSortedList_Asc = class(TConformance_TSortedList) 50 | protected 51 | function GetSortOrder: Boolean; override; 52 | end; 53 | 54 | TConformance_TSortedList_Desc = class(TConformance_TSortedList) 55 | protected 56 | function GetSortOrder: Boolean; override; 57 | end; 58 | 59 | TConformance_TLinkedList = class(TConformance_ILinkedList) 60 | protected 61 | procedure SetUp_ILinkedList(out AEmpty, AOne, AFull: ILinkedList; out AElements: TElements; out AOrdering: TOrdering); override; 62 | published 63 | end; 64 | 65 | TConformance_TSortedLinkedList = class(TConformance_ILinkedList) 66 | protected 67 | function GetSortOrder: Boolean; virtual; abstract; 68 | procedure SetUp_ILinkedList(out AEmpty, AOne, AFull: ILinkedList; out AElements: TElements; out AOrdering: TOrdering); override; 69 | published 70 | end; 71 | 72 | TConformance_TSortedLinkedList_Asc = class(TConformance_TSortedLinkedList) 73 | protected 74 | function GetSortOrder: Boolean; override; 75 | end; 76 | 77 | TConformance_TSortedLinkedList_Desc = class(TConformance_TSortedLinkedList) 78 | protected 79 | function GetSortOrder: Boolean; override; 80 | end; 81 | 82 | implementation 83 | 84 | { TConformance_TList } 85 | 86 | procedure TConformance_TList.SetUp_IList(out AEmpty, AOne, 87 | AFull: IList; out AElements: TElements; out AOrdering: TOrdering); 88 | var 89 | LItem: NativeInt; 90 | LEmpty, LOne, LFull: TList; 91 | begin 92 | AElements := GenerateRepeatableRandomElements(); 93 | AOrdering := oInsert; 94 | 95 | LEmpty := TList.Create(); LEmpty.RemoveNotification := RemoveNotification; 96 | LOne := TList.Create(); LOne.RemoveNotification := RemoveNotification; 97 | LOne.Add(AElements[0]); 98 | LFull := TList.Create(); LFull.RemoveNotification := RemoveNotification; 99 | 100 | for LItem in AElements do 101 | LFull.Add(LItem); 102 | 103 | AEmpty := LEmpty; 104 | AOne := LOne; 105 | AFull := LFull; 106 | end; 107 | 108 | { TConformance_TLinkedList } 109 | 110 | procedure TConformance_TLinkedList.SetUp_ILinkedList(out AEmpty, AOne, 111 | AFull: ILinkedList; out AElements: TElements; 112 | out AOrdering: TOrdering); 113 | var 114 | LItem: NativeInt; 115 | LEmpty, LOne, LFull: TLinkedList; 116 | begin 117 | AElements := GenerateRepeatableRandomElements(); 118 | AOrdering := oInsert; 119 | 120 | LEmpty := TLinkedList.Create(); LEmpty.RemoveNotification := RemoveNotification; 121 | LOne := TLinkedList.Create(); LOne.RemoveNotification := RemoveNotification; 122 | LOne.Add(AElements[0]); 123 | LFull := TLinkedList.Create(); LFull.RemoveNotification := RemoveNotification; 124 | 125 | for LItem in AElements do 126 | LFull.Add(LItem); 127 | 128 | AEmpty := LEmpty; 129 | AOne := LOne; 130 | AFull := LFull; 131 | end; 132 | 133 | { TConformance_TSortedList } 134 | 135 | procedure TConformance_TSortedList.SetUp_IList(out AEmpty, AOne, 136 | AFull: IList; out AElements: TElements; out AOrdering: TOrdering); 137 | var 138 | LItem: NativeInt; 139 | LEmpty, LOne, LFull: TSortedList; 140 | begin 141 | AElements := GenerateRepeatableRandomElements(); 142 | 143 | if GetSortOrder then 144 | AOrdering := oAscending 145 | else 146 | AOrdering := oDescending; 147 | 148 | LEmpty := TSortedList.Create(TRules.Default, 0, GetSortOrder); LEmpty.RemoveNotification := RemoveNotification; 149 | LOne := TSortedList.Create(TRules.Default, 0, GetSortOrder); LOne.RemoveNotification := RemoveNotification; 150 | LOne.Add(AElements[0]); 151 | LFull := TSortedList.Create(TRules.Default, 0, GetSortOrder); LFull.RemoveNotification := RemoveNotification; 152 | 153 | for LItem in AElements do 154 | LFull.Add(LItem); 155 | 156 | AEmpty := LEmpty; 157 | AOne := LOne; 158 | AFull := LFull; 159 | end; 160 | 161 | { TConformance_TSortedList_Asc } 162 | 163 | function TConformance_TSortedList_Asc.GetSortOrder: Boolean; 164 | begin 165 | Result := True; 166 | end; 167 | 168 | { TConformance_TSortedList_Desc } 169 | 170 | function TConformance_TSortedList_Desc.GetSortOrder: Boolean; 171 | begin 172 | Result := False; 173 | end; 174 | 175 | { TConformance_TSortedLinkedList } 176 | 177 | procedure TConformance_TSortedLinkedList.SetUp_ILinkedList(out AEmpty, AOne, 178 | AFull: ILinkedList; out AElements: TElements; 179 | out AOrdering: TOrdering); 180 | var 181 | LItem: NativeInt; 182 | LEmpty, LOne, LFull: TSortedLinkedList; 183 | begin 184 | AElements := GenerateRepeatableRandomElements(); 185 | 186 | if GetSortOrder then 187 | AOrdering := oAscending 188 | else 189 | AOrdering := oDescending; 190 | 191 | LEmpty := TSortedLinkedList.Create(TRules.Default, GetSortOrder); LEmpty.RemoveNotification := RemoveNotification; 192 | LOne := TSortedLinkedList.Create(TRules.Default, GetSortOrder); LOne.RemoveNotification := RemoveNotification; 193 | LOne.Add(AElements[0]); 194 | LFull := TSortedLinkedList.Create(TRules.Default, GetSortOrder); LFull.RemoveNotification := RemoveNotification; 195 | 196 | for LItem in AElements do 197 | LFull.Add(LItem); 198 | 199 | AEmpty := LEmpty; 200 | AOne := LOne; 201 | AFull := LFull; 202 | end; 203 | 204 | { TConformance_TSortedLinkedList_Asc } 205 | 206 | function TConformance_TSortedLinkedList_Asc.GetSortOrder: Boolean; 207 | begin 208 | Result := True; 209 | end; 210 | 211 | { TConformance_TSortedLinkedList_Desc } 212 | 213 | function TConformance_TSortedLinkedList_Desc.GetSortOrder: Boolean; 214 | begin 215 | Result := False; 216 | end; 217 | 218 | initialization 219 | RegisterTests('Conformance.Simple.Lists', [ 220 | TConformance_TList.Suite, 221 | TConformance_TSortedList_Asc.Suite, 222 | TConformance_TSortedList_Desc.Suite, 223 | TConformance_TLinkedList.Suite, 224 | TConformance_TSortedLinkedList_Asc.Suite, 225 | TConformance_TSortedLinkedList_Desc.Suite 226 | ]); 227 | 228 | end. 229 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.MultiMaps.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | { 29 | This file has been modified from the original by Peter Johnson 30 | (@delphidabbler). For full details of modifications see the commit history of 31 | the delphidabbler/delphi-coll fork on GitHub 32 | } 33 | 34 | 35 | unit Tests.Conformance.MultiMaps; 36 | interface 37 | uses SysUtils, 38 | Tests.Conformance.Base, 39 | TestFramework, 40 | Generics.Collections, 41 | Collections.Base, 42 | Collections.MultiMaps; 43 | 44 | type 45 | // TODO: Implement this test class 46 | TConformance_TMultiMap = class(TConformance_IMultiMap) 47 | protected 48 | procedure SetUp_IMultiMap(out AEmpty, AOne, AFull: IMultiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 49 | published 50 | end; 51 | 52 | // TODO: Implement this test class 53 | TConformance_TSortedMultiMap = class(TConformance_IMultiMap) 54 | protected 55 | procedure SetUp_IMultiMap(out AEmpty, AOne, AFull: IMultiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 56 | published 57 | end; 58 | 59 | // TODO: Implement this test class 60 | TConformance_TDoubleSortedMultiMap = class(TConformance_IMultiMap) 61 | protected 62 | procedure SetUp_IMultiMap(out AEmpty, AOne, AFull: IMultiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 63 | published 64 | end; 65 | 66 | // TODO: Implement this test class 67 | TConformance_TDistinctMultiMap = class(TConformance_IMultiMap) 68 | protected 69 | procedure SetUp_IMultiMap(out AEmpty, AOne, AFull: IMultiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 70 | published 71 | end; 72 | 73 | // TODO: Implement this test class 74 | TConformance_TSortedDistinctMultiMap = class(TConformance_IMultiMap) 75 | protected 76 | procedure SetUp_IMultiMap(out AEmpty, AOne, AFull: IMultiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 77 | published 78 | end; 79 | 80 | // TODO: Implement this test class 81 | TConformance_TDoubleSortedDistinctMultiMap = class(TConformance_IMultiMap) 82 | protected 83 | procedure SetUp_IMultiMap(out AEmpty, AOne, AFull: IMultiMap; out APairs: TPairs; out AKeyOrdering: TOrdering); override; 84 | published 85 | end; 86 | 87 | type 88 | // TODO: Implement this test class 89 | TConformance_TMultiMap_Keys = class(TConformance_ISequence) 90 | protected 91 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 92 | published 93 | end; 94 | 95 | // TODO: Implement this test class 96 | TConformance_TMultiMap_Values = class(TConformance_ISequence) 97 | protected 98 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 99 | published 100 | end; 101 | 102 | // TODO: Implement this test class 103 | TConformance_TSortedMultiMap_Keys = class(TConformance_ISequence) 104 | protected 105 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 106 | published 107 | end; 108 | 109 | // TODO: Implement this test class 110 | TConformance_TSortedMultiMap_Values = class(TConformance_ISequence) 111 | protected 112 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 113 | published 114 | end; 115 | 116 | // TODO: Implement this test class 117 | TConformance_TDoubleSortedMultiMap_Keys = class(TConformance_ISequence) 118 | protected 119 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 120 | published 121 | end; 122 | 123 | // TODO: Implement this test class 124 | TConformance_TDoubleSortedMultiMap_Values = class(TConformance_ISequence) 125 | protected 126 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 127 | published 128 | end; 129 | 130 | // TODO: Implement this test class 131 | TConformance_TDistinctMultiMap_Keys = class(TConformance_ISequence) 132 | protected 133 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 134 | published 135 | end; 136 | 137 | // TODO: Implement this test class 138 | TConformance_TDistinctMultiMap_Values = class(TConformance_ISequence) 139 | protected 140 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 141 | published 142 | end; 143 | 144 | // TODO: Implement this test class 145 | TConformance_TSortedDistinctMultiMap_Keys = class(TConformance_ISequence) 146 | protected 147 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 148 | published 149 | end; 150 | 151 | // TODO: Implement this test class 152 | TConformance_TSortedDistinctMultiMap_Values = class(TConformance_ISequence) 153 | protected 154 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 155 | published 156 | end; 157 | 158 | // TODO: Implement this test class 159 | TConformance_TDoubleSortedDistinctMultiMap_Keys = class(TConformance_ISequence) 160 | protected 161 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 162 | published 163 | end; 164 | 165 | // TODO: Implement this test class 166 | TConformance_TDoubleSortedDistinctMultiMap_Values = class(TConformance_ISequence) 167 | protected 168 | procedure SetUp_ISequence(out AEmpty, AOne, AFull: ISequence; out AElements: TElements; out AOrdering: TOrdering); override; 169 | published 170 | end; 171 | 172 | implementation 173 | 174 | { TConformance_TMultiMap } 175 | 176 | procedure TConformance_TMultiMap.SetUp_IMultiMap(out AEmpty, AOne, 177 | AFull: IMultiMap; out APairs: TPairs; 178 | out AKeyOrdering: TOrdering); 179 | begin 180 | // TODO: Set maps up correctly 181 | AEmpty := TMultiMap.Create; 182 | AOne := TMultiMap.Create; 183 | AFull := TMultiMap.Create; 184 | SetLength(APairs, 0); 185 | AKeyOrdering := oNone; 186 | end; 187 | 188 | { TConformance_TSortedMultiMap } 189 | 190 | procedure TConformance_TSortedMultiMap.SetUp_IMultiMap(out AEmpty, AOne, 191 | AFull: IMultiMap; out APairs: TPairs; 192 | out AKeyOrdering: TOrdering); 193 | begin 194 | // TODO: Set maps up correctly 195 | AEmpty := TSortedMultiMap.Create; 196 | AOne := TSortedMultiMap.Create; 197 | AFull := TSortedMultiMap.Create; 198 | SetLength(APairs, 0); 199 | AKeyOrdering := oAscending; 200 | end; 201 | 202 | { TConformance_TDoubleSortedMultiMap } 203 | 204 | procedure TConformance_TDoubleSortedMultiMap.SetUp_IMultiMap(out AEmpty, AOne, 205 | AFull: IMultiMap; out APairs: TPairs; 206 | out AKeyOrdering: TOrdering); 207 | begin 208 | // TODO: Set maps up correctly 209 | AEmpty := TDoubleSortedMultiMap.Create; 210 | AOne := TDoubleSortedMultiMap.Create; 211 | AFull := TDoubleSortedMultiMap.Create; 212 | SetLength(APairs, 0); 213 | AKeyOrdering := oDescending; 214 | end; 215 | 216 | { TConformance_TDistinctMultiMap } 217 | 218 | procedure TConformance_TDistinctMultiMap.SetUp_IMultiMap(out AEmpty, AOne, 219 | AFull: IMultiMap; out APairs: TPairs; 220 | out AKeyOrdering: TOrdering); 221 | begin 222 | // TODO: Set maps up correctly 223 | AEmpty := TDistinctMultiMap.Create; 224 | AOne := TDistinctMultiMap.Create; 225 | AFull := TDistinctMultiMap.Create; 226 | SetLength(APairs, 0); 227 | AKeyOrdering := oNone; 228 | end; 229 | 230 | { TConformance_TSortedDistinctMultiMap } 231 | 232 | procedure TConformance_TSortedDistinctMultiMap.SetUp_IMultiMap(out AEmpty, AOne, 233 | AFull: IMultiMap; out APairs: TPairs; 234 | out AKeyOrdering: TOrdering); 235 | begin 236 | // TODO: Set maps up correctly 237 | AEmpty := TSortedDistinctMultiMap.Create; 238 | AOne := TSortedDistinctMultiMap.Create; 239 | AFull := TSortedDistinctMultiMap.Create; 240 | SetLength(APairs, 0); 241 | AKeyOrdering := oAscending; 242 | end; 243 | 244 | { TConformance_TDoubleSortedDistinctMultiMap } 245 | 246 | procedure TConformance_TDoubleSortedDistinctMultiMap.SetUp_IMultiMap(out AEmpty, 247 | AOne, AFull: IMultiMap; out APairs: TPairs; 248 | out AKeyOrdering: TOrdering); 249 | begin 250 | // TODO: Set maps up correctly 251 | AEmpty := TDoubleSortedDistinctMultiMap.Create; 252 | AOne := TDoubleSortedDistinctMultiMap.Create; 253 | AFull := TDoubleSortedDistinctMultiMap.Create; 254 | SetLength(APairs, 0); 255 | AKeyOrdering := oDescending; 256 | end; 257 | 258 | { TConformance_TMultiMap_Keys } 259 | 260 | procedure TConformance_TMultiMap_Keys.SetUp_ISequence(out AEmpty, AOne, 261 | AFull: ISequence; out AElements: TElements; 262 | out AOrdering: TOrdering); 263 | var 264 | LMap: IMultiMap; 265 | begin 266 | // TODO: Set maps up correctly 267 | LMap := TMultiMap.Create; 268 | AEmpty := LMap.Keys; 269 | AOne := LMap.Keys; 270 | AFull := LMap.Keys; 271 | SetLength(AElements, 0); 272 | AOrdering := oNone; 273 | end; 274 | 275 | { TConformance_TMultiMap_Values } 276 | 277 | procedure TConformance_TMultiMap_Values.SetUp_ISequence(out AEmpty, AOne, 278 | AFull: ISequence; out AElements: TElements; 279 | out AOrdering: TOrdering); 280 | var 281 | LMap: IMultiMap; 282 | begin 283 | // TODO: Set maps up correctly 284 | LMap := TMultiMap.Create; 285 | AEmpty := LMap.Values; 286 | AOne := LMap.Values; 287 | AFull := LMap.Values; 288 | SetLength(AElements, 0); 289 | AOrdering := oNone; 290 | end; 291 | 292 | { TConformance_TSortedMultiMap_Keys } 293 | 294 | procedure TConformance_TSortedMultiMap_Keys.SetUp_ISequence(out AEmpty, AOne, 295 | AFull: ISequence; out AElements: TElements; 296 | out AOrdering: TOrdering); 297 | var 298 | LMap: IMultiMap; 299 | begin 300 | // TODO: Set maps up correctly 301 | LMap := TSortedMultiMap.Create; 302 | AEmpty := LMap.Keys; 303 | AOne := LMap.Keys; 304 | AFull := LMap.Keys; 305 | SetLength(AElements, 0); 306 | AOrdering := oDescending; 307 | end; 308 | 309 | { TConformance_TSortedMultiMap_Values } 310 | 311 | procedure TConformance_TSortedMultiMap_Values.SetUp_ISequence(out AEmpty, AOne, 312 | AFull: ISequence; out AElements: TElements; 313 | out AOrdering: TOrdering); 314 | var 315 | LMap: IMultiMap; 316 | begin 317 | // TODO: Set maps up correctly 318 | LMap := TSortedMultiMap.Create; 319 | AEmpty := LMap.Values; 320 | AOne := LMap.Values; 321 | AFull := LMap.Values; 322 | SetLength(AElements, 0); 323 | AOrdering := oDescending; 324 | end; 325 | 326 | { TConformance_TDoubleSortedMultiMap_Keys } 327 | 328 | procedure TConformance_TDoubleSortedMultiMap_Keys.SetUp_ISequence(out AEmpty, 329 | AOne, AFull: ISequence; out AElements: TElements; 330 | out AOrdering: TOrdering); 331 | var 332 | LMap: IMultiMap; 333 | begin 334 | // TODO: Set maps up correctly 335 | LMap := TDoubleSortedMultiMap.Create; 336 | AEmpty := LMap.Keys; 337 | AOne := LMap.Keys; 338 | AFull := LMap.Keys; 339 | SetLength(AElements, 0); 340 | AOrdering := oAscending; 341 | end; 342 | 343 | { TConformance_TDoubleSortedMultiMap_Values } 344 | 345 | procedure TConformance_TDoubleSortedMultiMap_Values.SetUp_ISequence(out AEmpty, 346 | AOne, AFull: ISequence; out AElements: TElements; 347 | out AOrdering: TOrdering); 348 | var 349 | LMap: IMultiMap; 350 | begin 351 | // TODO: Set maps up correctly 352 | LMap := TDoubleSortedMultiMap.Create; 353 | AEmpty := LMap.Values; 354 | AOne := LMap.Values; 355 | AFull := LMap.Values; 356 | SetLength(AElements, 0); 357 | AOrdering := oAscending; 358 | end; 359 | 360 | { TConformance_TDistinctMultiMap_Keys } 361 | 362 | procedure TConformance_TDistinctMultiMap_Keys.SetUp_ISequence(out AEmpty, AOne, 363 | AFull: ISequence; out AElements: TElements; 364 | out AOrdering: TOrdering); 365 | var 366 | LMap: IMultiMap; 367 | begin 368 | // TODO: Set maps up correctly 369 | LMap := TDistinctMultiMap.Create; 370 | AEmpty := LMap.Keys; 371 | AOne := LMap.Keys; 372 | AFull := LMap.Keys; 373 | SetLength(AElements, 0); 374 | AOrdering := oNone; 375 | end; 376 | 377 | { TConformance_TDistinctMultiMap_Values } 378 | 379 | procedure TConformance_TDistinctMultiMap_Values.SetUp_ISequence(out AEmpty, 380 | AOne, AFull: ISequence; out AElements: TElements; 381 | out AOrdering: TOrdering); 382 | var 383 | LMap: IMultiMap; 384 | begin 385 | // TODO: Set maps up correctly 386 | LMap := TDistinctMultiMap.Create; 387 | AEmpty := LMap.Values; 388 | AOne := LMap.Values; 389 | AFull := LMap.Values; 390 | SetLength(AElements, 0); 391 | AOrdering := oNone; 392 | end; 393 | 394 | { TConformance_TSortedDistinctMultiMap_Keys } 395 | 396 | procedure TConformance_TSortedDistinctMultiMap_Keys.SetUp_ISequence(out AEmpty, 397 | AOne, AFull: ISequence; out AElements: TElements; 398 | out AOrdering: TOrdering); 399 | var 400 | LMap: IMultiMap; 401 | begin 402 | // TODO: Set maps up correctly 403 | LMap := TSortedDistinctMultiMap.Create; 404 | AEmpty := LMap.Keys; 405 | AOne := LMap.Keys; 406 | AFull := LMap.Keys; 407 | SetLength(AElements, 0); 408 | AOrdering := oAscending; 409 | end; 410 | 411 | { TConformance_TSortedDistinctMultiMap_Values } 412 | 413 | procedure TConformance_TSortedDistinctMultiMap_Values.SetUp_ISequence( 414 | out AEmpty, AOne, AFull: ISequence; out AElements: TElements; 415 | out AOrdering: TOrdering); 416 | var 417 | LMap: IMultiMap; 418 | begin 419 | // TODO: Set maps up correctly 420 | LMap := TSortedDistinctMultiMap.Create; 421 | AEmpty := LMap.Values; 422 | AOne := LMap.Values; 423 | AFull := LMap.Values; 424 | SetLength(AElements, 0); 425 | AOrdering := oAscending; 426 | end; 427 | 428 | { TConformance_TDoubleSortedDistinctMultiMap_Keys } 429 | 430 | procedure TConformance_TDoubleSortedDistinctMultiMap_Keys.SetUp_ISequence( 431 | out AEmpty, AOne, AFull: ISequence; out AElements: TElements; 432 | out AOrdering: TOrdering); 433 | var 434 | LMap: IMultiMap; 435 | begin 436 | // TODO: Set maps up correctly 437 | LMap := TDoubleSortedDistinctMultiMap.Create; 438 | AEmpty := LMap.Keys; 439 | AOne := LMap.Keys; 440 | AFull := LMap.Keys; 441 | SetLength(AElements, 0); 442 | AOrdering := oDescending; 443 | end; 444 | 445 | { TConformance_TDoubleSortedDistinctMultiMap_Values } 446 | 447 | procedure TConformance_TDoubleSortedDistinctMultiMap_Values.SetUp_ISequence( 448 | out AEmpty, AOne, AFull: ISequence; out AElements: TElements; 449 | out AOrdering: TOrdering); 450 | var 451 | LMap: IMultiMap; 452 | begin 453 | // TODO: Set maps up correctly 454 | LMap := TDoubleSortedDistinctMultiMap.Create; 455 | AEmpty := LMap.Values; 456 | AOne := LMap.Values; 457 | AFull := LMap.Values; 458 | SetLength(AElements, 0); 459 | AOrdering := oDescending; 460 | end; 461 | 462 | initialization 463 | RegisterTests('Conformance.Associative.MultiMaps', [ 464 | TConformance_TMultiMap.Suite, 465 | TConformance_TSortedMultiMap.Suite, 466 | TConformance_TDoubleSortedMultiMap.Suite, 467 | TConformance_TDistinctMultiMap.Suite, 468 | TConformance_TSortedDistinctMultiMap.Suite, 469 | TConformance_TDoubleSortedDistinctMultiMap.Suite 470 | ]); 471 | 472 | RegisterTests('Conformance.Simple.Selectors', [ 473 | TConformance_TMultiMap_Keys.Suite, 474 | TConformance_TMultiMap_Values.Suite, 475 | TConformance_TSortedMultiMap_Keys.Suite, 476 | TConformance_TSortedMultiMap_Values.Suite, 477 | TConformance_TDoubleSortedMultiMap_Keys.Suite, 478 | TConformance_TDoubleSortedMultiMap_Values.Suite, 479 | TConformance_TDistinctMultiMap_Keys.Suite, 480 | TConformance_TDistinctMultiMap_Values.Suite, 481 | TConformance_TSortedDistinctMultiMap_Keys.Suite, 482 | TConformance_TSortedDistinctMultiMap_Values.Suite, 483 | TConformance_TDoubleSortedDistinctMultiMap_Keys.Suite, 484 | TConformance_TDoubleSortedDistinctMultiMap_Values.Suite 485 | ]); 486 | 487 | end. 488 | 489 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.Queues.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | unit Tests.Conformance.Queues; 29 | interface 30 | uses SysUtils, 31 | Tests.Conformance.Base, 32 | TestFramework, 33 | Generics.Collections, 34 | Collections.Base, 35 | Collections.Lists, 36 | Collections.Queues; 37 | 38 | type 39 | TConformance_TQueue = class(TConformance_IQueue) 40 | protected 41 | procedure SetUp_IQueue(out AEmpty, AOne, AFull: IQueue; out AElements: TElements; out AOrdering: TOrdering); override; 42 | published 43 | end; 44 | 45 | TConformance_TLinkedQueue = class(TConformance_IQueue) 46 | protected 47 | procedure SetUp_IQueue(out AEmpty, AOne, AFull: IQueue; out AElements: TElements; out AOrdering: TOrdering); override; 48 | published 49 | end; 50 | 51 | TConformance_TLinkedList_AsQueue = class(TConformance_IQueue) 52 | protected 53 | procedure SetUp_IQueue(out AEmpty, AOne, AFull: IQueue; out AElements: TElements; out AOrdering: TOrdering); override; 54 | published 55 | end; 56 | 57 | implementation 58 | 59 | { TConformance_TQueue } 60 | 61 | procedure TConformance_TQueue.SetUp_IQueue(out AEmpty, AOne, 62 | AFull: IQueue; out AElements: TElements; out AOrdering: TOrdering); 63 | var 64 | LItem: NativeInt; 65 | LEmpty, LOne, LFull: TQueue; 66 | begin 67 | AElements := GenerateRepeatableRandomElements(); 68 | AOrdering := oInsert; 69 | 70 | LEmpty := TQueue.Create(); LEmpty.RemoveNotification := RemoveNotification; 71 | LOne := TQueue.Create(); LOne.RemoveNotification := RemoveNotification; 72 | LOne.Enqueue(AElements[0]); 73 | LFull := TQueue.Create(); LFull.RemoveNotification := RemoveNotification; 74 | 75 | for LItem in AElements do 76 | LFull.Enqueue(LItem); 77 | 78 | AEmpty := LEmpty; 79 | AOne := LOne; 80 | AFull := LFull; 81 | end; 82 | 83 | { TConformance_TLinkedQueue } 84 | 85 | procedure TConformance_TLinkedQueue.SetUp_IQueue(out AEmpty, AOne, 86 | AFull: IQueue; out AElements: TElements; out AOrdering: TOrdering); 87 | var 88 | LItem: NativeInt; 89 | LEmpty, LOne, LFull: TLinkedQueue; 90 | begin 91 | AElements := GenerateRepeatableRandomElements(); 92 | AOrdering := oInsert; 93 | 94 | LEmpty := TLinkedQueue.Create(); LEmpty.RemoveNotification := RemoveNotification; 95 | LOne := TLinkedQueue.Create(); LOne.RemoveNotification := RemoveNotification; 96 | LOne.Enqueue(AElements[0]); 97 | LFull := TLinkedQueue.Create(); LFull.RemoveNotification := RemoveNotification; 98 | 99 | for LItem in AElements do 100 | LFull.Enqueue(LItem); 101 | 102 | AEmpty := LEmpty; 103 | AOne := LOne; 104 | AFull := LFull; 105 | end; 106 | 107 | { TConformance_TLinkedList_AsQueue } 108 | 109 | procedure TConformance_TLinkedList_AsQueue.SetUp_IQueue(out AEmpty, AOne, 110 | AFull: IQueue; out AElements: TElements; out AOrdering: TOrdering); 111 | var 112 | LItem: NativeInt; 113 | LEmpty, LOne, LFull: TLinkedList; 114 | begin 115 | AElements := GenerateRepeatableRandomElements(); 116 | AOrdering := oInsert; 117 | 118 | LEmpty := TLinkedList.Create(); LEmpty.RemoveNotification := RemoveNotification; 119 | LOne := TLinkedList.Create(); LOne.RemoveNotification := RemoveNotification; 120 | LOne.AddLast(AElements[0]); 121 | LFull := TLinkedList.Create(); LFull.RemoveNotification := RemoveNotification; 122 | 123 | for LItem in AElements do 124 | LFull.AddLast(LItem); 125 | 126 | AEmpty := LEmpty; 127 | AOne := LOne; 128 | AFull := LFull; 129 | end; 130 | 131 | initialization 132 | RegisterTests('Conformance.Simple.Queues', [ 133 | TConformance_TQueue.Suite, 134 | TConformance_TLinkedQueue.Suite, 135 | TConformance_TLinkedList_AsQueue.Suite 136 | ]); 137 | 138 | end. 139 | 140 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.Specific.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | { 29 | This file has been modified from the original by Peter Johnson 30 | (@delphidabbler). For full details of modifications see the commit history of 31 | the delphidabbler/delphi-coll fork on GitHub 32 | } 33 | 34 | 35 | unit Tests.Conformance.Specific; 36 | interface 37 | uses SysUtils, 38 | Tests.Internal.Basics, 39 | Tests.Conformance.Base, 40 | TestFramework, 41 | Generics.Collections, 42 | Collections.Base, 43 | Collections.Sets; 44 | 45 | type 46 | // NOTE: Temporary class that all un-implemented classes descend from: used simply to get a fail test 47 | // When a test is implemented change its parent class back to the commented out version and 48 | // provide concrete implementations of inherited abstract methods. 49 | TSpecificTempTest = class(TTestCaseEx) 50 | published 51 | procedure Test_STUB; 52 | end; 53 | 54 | // TODO: restore following parent class when implementing test(s) 55 | // TConformance_TCollection = class(TConformance_ICollection) 56 | TConformance_TCollection = class(TSpecificTempTest) 57 | published 58 | // TODO: Implement tests 59 | end; 60 | 61 | // TODO: restore following parent class when implementing test(s) 62 | // TConformance_TAbstractMap = class(TConformance_IMap) 63 | TConformance_TAbstractMap = class(TSpecificTempTest) 64 | published 65 | // TODO: Implement tests 66 | end; 67 | 68 | // TODO: restore following parent class when implementing test(s) 69 | // TConformance_ISequence_Op_GroupBy = class(TConformance_IGrouping) 70 | TConformance_ISequence_Op_GroupBy = class(TSpecificTempTest) 71 | published 72 | // TODO: Implement tests 73 | end; 74 | 75 | // TODO: restore following parent class when implementing test(s) 76 | // TConformance_ISequence_ToList = class(TConformance_IList) 77 | TConformance_ISequence_ToList = class(TSpecificTempTest) 78 | published 79 | // TODO: Implement tests 80 | end; 81 | 82 | // TODO: restore following parent class when implementing test(s) 83 | // TConformance_ISequence_ToSet = class(TConformance_ISet) 84 | TConformance_ISequence_ToSet = class(TSpecificTempTest) 85 | published 86 | // TODO: Implement tests 87 | end; 88 | 89 | // TODO: restore following parent class when implementing test(s) 90 | // TConformance_ISequence_Where = class(TConformance_ISequence) 91 | TConformance_ISequence_Where = class(TSpecificTempTest) 92 | published 93 | // TODO: Implement tests 94 | end; 95 | 96 | // TODO: restore following parent class when implementing test(s) 97 | // TConformance_ISequence_Distinct = class(TConformance_ISequence) 98 | TConformance_ISequence_Distinct = class(TSpecificTempTest) 99 | published 100 | // TODO: Implement tests 101 | end; 102 | 103 | // TODO: restore following parent class when implementing test(s) 104 | // TConformance_ISequence_Ordered_1 = class(TConformance_ISequence) 105 | TConformance_ISequence_Ordered_1 = class(TSpecificTempTest) 106 | published 107 | // TODO: Implement tests 108 | end; 109 | 110 | // TODO: restore following parent class when implementing test(s) 111 | // TConformance_ISequence_Ordered_2 = class(TConformance_ISequence) 112 | TConformance_ISequence_Ordered_2 = class(TSpecificTempTest) 113 | published 114 | // TODO: Implement tests 115 | end; 116 | 117 | // TODO: restore following parent class when implementing test(s) 118 | // TConformance_ISequence_Reversed = class(TConformance_ISequence) 119 | TConformance_ISequence_Reversed = class(TSpecificTempTest) 120 | published 121 | // TODO: Implement tests 122 | end; 123 | 124 | // TODO: restore following parent class when implementing test(s) 125 | // TConformance_ISequence_Concat = class(TConformance_ISequence) 126 | TConformance_ISequence_Concat = class(TSpecificTempTest) 127 | published 128 | // TODO: Implement tests 129 | end; 130 | 131 | // TODO: restore following parent class when implementing test(s) 132 | // TConformance_ISequence_Union = class(TConformance_ISequence) 133 | TConformance_ISequence_Union = class(TSpecificTempTest) 134 | published 135 | // TODO: Implement tests 136 | end; 137 | 138 | // TODO: restore following parent class when implementing test(s) 139 | // TConformance_ISequence_Exclude = class(TConformance_ISequence) 140 | TConformance_ISequence_Exclude = class(TSpecificTempTest) 141 | published 142 | // TODO: Implement tests 143 | end; 144 | 145 | // TODO: restore following parent class when implementing test(s) 146 | // TConformance_ISequence_Intersect = class(TConformance_ISequence) 147 | TConformance_ISequence_Intersect = class(TSpecificTempTest) 148 | published 149 | // TODO: Implement tests 150 | end; 151 | 152 | // TODO: restore following parent class when implementing test(s) 153 | // TConformance_ISequence_Range = class(TConformance_ISequence) 154 | TConformance_ISequence_Range = class(TSpecificTempTest) 155 | published 156 | // TODO: Implement tests 157 | end; 158 | 159 | // TODO: restore following parent class when implementing test(s) 160 | // TConformance_ISequence_Take = class(TConformance_ISequence) 161 | TConformance_ISequence_Take = class(TSpecificTempTest) 162 | published 163 | // TODO: Implement tests 164 | end; 165 | 166 | // TODO: restore following parent class when implementing test(s) 167 | // TConformance_ISequence_TakeWhile = class(TConformance_ISequence) 168 | TConformance_ISequence_TakeWhile = class(TSpecificTempTest) 169 | published 170 | // TODO: Implement tests 171 | end; 172 | 173 | // TODO: restore following parent class when implementing test(s) 174 | // TConformance_ISequence_Skip = class(TConformance_ISequence) 175 | TConformance_ISequence_Skip = class(TSpecificTempTest) 176 | published 177 | // TODO: Implement tests 178 | end; 179 | 180 | // TODO: restore following parent class when implementing test(s) 181 | // TConformance_ISequence_SkipWhile = class(TConformance_ISequence) 182 | TConformance_ISequence_SkipWhile = class(TSpecificTempTest) 183 | published 184 | // TODO: Implement tests 185 | end; 186 | 187 | // TODO: restore following parent class when implementing test(s) 188 | // TConformance_ISequence_Op_Select_1 = class(TConformance_ISequence) 189 | TConformance_ISequence_Op_Select_1 = class(TSpecificTempTest) 190 | published 191 | // TODO: Implement tests 192 | end; 193 | 194 | // TODO: restore following parent class when implementing test(s) 195 | // TConformance_ISequence_Op_Select_2 = class(TConformance_ISequence) 196 | TConformance_ISequence_Op_Select_2 = class(TSpecificTempTest) 197 | published 198 | // TODO: Implement tests 199 | end; 200 | 201 | // TODO: restore following parent class when implementing test(s) 202 | // TConformance_ISequence_Op_Select_3 = class(TConformance_ISequence) 203 | TConformance_ISequence_Op_Select_3 = class(TSpecificTempTest) 204 | published 205 | // TODO: Implement tests 206 | end; 207 | 208 | // TODO: restore following parent class when implementing test(s) 209 | // TConformance_ISequence_Op_Select_4 = class(TConformance_ISequence) 210 | TConformance_ISequence_Op_Select_4 = class(TSpecificTempTest) 211 | published 212 | // TODO: Implement tests 213 | end; 214 | 215 | // TODO: restore following parent class when implementing test(s) 216 | // TConformance_ISequence_Op_Select_5 = class(TConformance_ISequence) 217 | TConformance_ISequence_Op_Select_5 = class(TSpecificTempTest) 218 | published 219 | // TODO: Implement tests 220 | end; 221 | 222 | // TODO: restore following parent class when implementing test(s) 223 | // TConformance_IAssociation_ToDictionary = class(TConformance_IDictionary) 224 | TConformance_IAssociation_ToDictionary = class(TSpecificTempTest) 225 | published 226 | // TODO: Implement tests 227 | end; 228 | 229 | // TODO: restore following parent class when implementing test(s) 230 | // TConformance_IAssociation_SelectKeys = class(TConformance_ISequence) 231 | TConformance_IAssociation_SelectKeys = class(TSpecificTempTest) 232 | published 233 | // TODO: Implement tests 234 | end; 235 | 236 | // TODO: restore following parent class when implementing test(s) 237 | // TConformance_IAssociation_SelectValues = class(TConformance_ISequence) 238 | TConformance_IAssociation_SelectValues = class(TSpecificTempTest) 239 | published 240 | // TODO: Implement tests 241 | end; 242 | 243 | // TODO: restore following parent class when implementing test(s) 244 | // TConformance_IAssociation_DistinctByKeys = class(TConformance_IAssociation) 245 | TConformance_IAssociation_DistinctByKeys = class(TSpecificTempTest) 246 | published 247 | // TODO: Implement tests 248 | end; 249 | 250 | // TODO: restore following parent class when implementing test(s) 251 | // TConformance_IAssociation_DistinctByValues = class(TConformance_IAssociation) 252 | TConformance_IAssociation_DistinctByValues = class(TSpecificTempTest) 253 | published 254 | // TODO: Implement tests 255 | end; 256 | 257 | // TODO: restore following parent class when implementing test(s) 258 | // TConformance_IAssociation_Where = class(TConformance_IAssociation) 259 | TConformance_IAssociation_Where = class(TSpecificTempTest) 260 | published 261 | // TODO: Implement tests 262 | end; 263 | 264 | implementation 265 | 266 | { TSpecificTempTest } 267 | 268 | procedure TSpecificTempTest.Test_STUB; 269 | begin 270 | Fail('No tests implemented for ' + ClassName + '!'); 271 | end; 272 | 273 | initialization 274 | RegisterTests('Conformance.Simple.Specific', [ 275 | TConformance_ISequence_ToList.Suite, 276 | TConformance_ISequence_ToSet.Suite, 277 | TConformance_ISequence_Where.Suite, 278 | TConformance_ISequence_Distinct.Suite, 279 | TConformance_ISequence_Ordered_1.Suite, 280 | TConformance_ISequence_Ordered_2.Suite, 281 | TConformance_ISequence_Reversed.Suite, 282 | TConformance_ISequence_Concat.Suite, 283 | TConformance_ISequence_Union.Suite, 284 | TConformance_ISequence_Exclude.Suite, 285 | TConformance_ISequence_Intersect.Suite, 286 | TConformance_ISequence_Range.Suite, 287 | TConformance_ISequence_Take.Suite, 288 | TConformance_ISequence_TakeWhile.Suite, 289 | TConformance_ISequence_Skip.Suite, 290 | TConformance_ISequence_SkipWhile.Suite, 291 | TConformance_ISequence_Op_Select_1.Suite, 292 | TConformance_ISequence_Op_Select_2.Suite, 293 | TConformance_ISequence_Op_Select_3.Suite, 294 | TConformance_ISequence_Op_Select_4.Suite, 295 | TConformance_ISequence_Op_Select_5.Suite 296 | ]); 297 | 298 | RegisterTests('Conformance.Associative.Specific', [ 299 | TConformance_IAssociation_ToDictionary.Suite, 300 | TConformance_IAssociation_SelectKeys.Suite, 301 | TConformance_IAssociation_SelectValues.Suite, 302 | TConformance_IAssociation_DistinctByKeys.Suite, 303 | TConformance_IAssociation_DistinctByValues.Suite, 304 | TConformance_IAssociation_Where.Suite 305 | ]); 306 | 307 | end. 308 | 309 | -------------------------------------------------------------------------------- /src/Tests/Tests.Conformance.Stacks.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | unit Tests.Conformance.Stacks; 29 | interface 30 | uses SysUtils, 31 | Tests.Conformance.Base, 32 | TestFramework, 33 | Generics.Collections, 34 | Collections.Base, 35 | Collections.Lists, 36 | Collections.Stacks; 37 | 38 | type 39 | TConformance_TStack = class(TConformance_IStack) 40 | protected 41 | procedure SetUp_IStack(out AEmpty, AOne, AFull: IStack; out AElements: TElements; out AOrdering: TOrdering); override; 42 | published 43 | end; 44 | 45 | TConformance_TLinkedStack = class(TConformance_IStack) 46 | protected 47 | procedure SetUp_IStack(out AEmpty, AOne, AFull: IStack; out AElements: TElements; out AOrdering: TOrdering); override; 48 | published 49 | end; 50 | 51 | TConformance_TLinkedList_AsStack = class(TConformance_IStack) 52 | protected 53 | procedure SetUp_IStack(out AEmpty, AOne, AFull: IStack; out AElements: TElements; out AOrdering: TOrdering); override; 54 | published 55 | end; 56 | 57 | implementation 58 | 59 | { TConformance_TStack } 60 | 61 | procedure TConformance_TStack.SetUp_IStack(out AEmpty, AOne, AFull: IStack; out AElements: TElements; out AOrdering: TOrdering); 62 | var 63 | LItem: NativeInt; 64 | LEmpty, LOne, LFull: TStack; 65 | begin 66 | AElements := GenerateRepeatableRandomElements(); 67 | AOrdering := oInsert; 68 | 69 | LEmpty := TStack.Create(); LEmpty.RemoveNotification := RemoveNotification; 70 | LOne := TStack.Create(); LOne.RemoveNotification := RemoveNotification; 71 | LOne.Push(AElements[0]); 72 | LFull := TStack.Create(); LFull.RemoveNotification := RemoveNotification; 73 | 74 | for LItem in AElements do 75 | LFull.Push(LItem); 76 | 77 | AEmpty := LEmpty; 78 | AOne := LOne; 79 | AFull := LFull; 80 | end; 81 | 82 | { TConformance_TLinkedStack } 83 | 84 | procedure TConformance_TLinkedStack.SetUp_IStack(out AEmpty, AOne, AFull: IStack; out AElements: TElements; out AOrdering: TOrdering); 85 | var 86 | LItem: NativeInt; 87 | LEmpty, LOne, LFull: TLinkedStack; 88 | begin 89 | AElements := GenerateRepeatableRandomElements(); 90 | AOrdering := oInsert; 91 | 92 | LEmpty := TLinkedStack.Create(); LEmpty.RemoveNotification := RemoveNotification; 93 | LOne := TLinkedStack.Create(); LOne.RemoveNotification := RemoveNotification; 94 | LOne.Push(AElements[0]); 95 | LFull := TLinkedStack.Create(); LFull.RemoveNotification := RemoveNotification; 96 | 97 | for LItem in AElements do 98 | LFull.Push(LItem); 99 | 100 | AEmpty := LEmpty; 101 | AOne := LOne; 102 | AFull := LFull; 103 | end; 104 | 105 | { TConformance_TLinkedList_AsStack } 106 | 107 | procedure TConformance_TLinkedList_AsStack.SetUp_IStack(out AEmpty, AOne, 108 | AFull: IStack; out AElements: TElements; out AOrdering: TOrdering); 109 | var 110 | LItem: NativeInt; 111 | LEmpty, LOne, LFull: TLinkedList; 112 | begin 113 | AElements := GenerateRepeatableRandomElements(); 114 | AOrdering := oInsert; 115 | 116 | LEmpty := TLinkedList.Create(); LEmpty.RemoveNotification := RemoveNotification; 117 | LOne := TLinkedList.Create(); LOne.RemoveNotification := RemoveNotification; 118 | LOne.AddLast(AElements[0]); 119 | LFull := TLinkedList.Create(); LFull.RemoveNotification := RemoveNotification; 120 | 121 | for LItem in AElements do 122 | LFull.AddLast(LItem); 123 | 124 | AEmpty := LEmpty; 125 | AOne := LOne; 126 | AFull := LFull; 127 | end; 128 | 129 | 130 | initialization 131 | RegisterTests('Conformance.Simple.Stacks', [ 132 | TConformance_TStack.Suite, 133 | TConformance_TLinkedStack.Suite, 134 | TConformance_TLinkedList_AsStack.Suite 135 | ]); 136 | 137 | end. 138 | 139 | -------------------------------------------------------------------------------- /src/Tests/Tests.Internal.Basics.pas: -------------------------------------------------------------------------------- 1 | (* 2 | * Copyright (c) 2008-2011, Ciobanu Alexandru 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * * Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * * Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * * Neither the name of the nor the 13 | * names of its contributors may be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | *) 27 | 28 | unit Tests.Internal.Basics; 29 | interface 30 | uses 31 | SysUtils, 32 | TestFramework, 33 | Generics.Defaults, 34 | Collections.Base; 35 | 36 | type 37 | TClassOfException = class of Exception; 38 | 39 | { Our test case } 40 | TTestCaseEx = class(TTestCase) 41 | protected 42 | procedure CheckException(const AExType: TClassOfException; const AProc: TProc; const Msg : String); 43 | end; 44 | 45 | type 46 | TTestBase = class(TTestCaseEx) 47 | published 48 | procedure TestRefCountedObjectLife(); 49 | procedure TestRefCountedObjectExtractReference(); 50 | procedure TestRefCountedObjectKeepObjectAlive(); 51 | procedure TestRefCountedObjectReleaseObject(); 52 | procedure TestRefCountedObjectExceptions(); 53 | end; 54 | 55 | ICheck = interface 56 | procedure CheckNotConstructing(); 57 | procedure CheckRefCountEquals(const Cnt: Integer); 58 | end; 59 | 60 | TTestRefCountedObject = class(TRefCountedObject, ICheck) 61 | private 62 | FTest: TTestBase; 63 | 64 | public 65 | constructor Create(const Test: TTestBase); 66 | 67 | procedure CheckNotConstructing(); 68 | procedure CheckRefCountEquals(const Cnt: Integer); 69 | 70 | destructor Destroy(); override; 71 | end; 72 | 73 | TTestRules = class(TTestCaseEx) 74 | published 75 | procedure Test_Create; 76 | procedure Test_Custom; 77 | procedure Test_Default; 78 | end; 79 | 80 | type 81 | TInsensitiveStringComparer = class(TStringComparer) 82 | public 83 | function Compare(const Left, Right: string): Integer; override; 84 | function Equals(const Left, Right: string): Boolean; 85 | reintroduce; overload; override; 86 | function GetHashCode(const Value: string): Integer; 87 | reintroduce; overload; override; 88 | end; 89 | 90 | var 91 | StringCaseInsensitiveComparer: TInsensitiveStringComparer; 92 | 93 | 94 | implementation 95 | 96 | { TTestCaseEx } 97 | 98 | procedure TTestCaseEx.CheckException(const AExType: TClassOfException; const AProc: TProc; const Msg: String); 99 | var 100 | bWasEx : Boolean; 101 | begin 102 | bWasEx := False; 103 | 104 | try 105 | { Cannot self-link } 106 | AProc(); 107 | except 108 | on E : Exception do 109 | begin 110 | if E is AExType then 111 | bWasEx := True; 112 | end; 113 | end; 114 | 115 | Check(bWasEx, Msg); 116 | end; 117 | 118 | 119 | var 120 | TestDestroy: Integer; 121 | 122 | { TTestBase } 123 | 124 | procedure TTestBase.TestRefCountedObjectKeepObjectAlive; 125 | var 126 | Obj, Obj1, Obj2: TTestRefCountedObject; 127 | I1, I2: ICheck; 128 | begin 129 | { ------------ No Interfaces, No destroy ----------- } 130 | TestDestroy := 0; 131 | 132 | Obj := TTestRefCountedObject.Create(Self); 133 | Obj1 := TTestRefCountedObject.Create(Self); 134 | Obj2 := TTestRefCountedObject.Create(Self); 135 | 136 | { Register for keep-alive } 137 | Obj.KeepObjectAlive(Obj1); 138 | Obj.KeepObjectAlive(Obj2); 139 | 140 | Obj.Free; 141 | Check(TestDestroy = 1, 'Only Obj expected to be gone!'); 142 | 143 | { ------------ Interfaces, No chain -------------} 144 | TestDestroy := 0; 145 | Obj := TTestRefCountedObject.Create(Self); 146 | I1 := Obj1; 147 | I2 := Obj2; 148 | 149 | { Should not allow Obj1 and 2 to be killed! } 150 | Obj.KeepObjectAlive(Obj1); 151 | Obj.KeepObjectAlive(Obj2); 152 | 153 | I1 := nil; 154 | I2 := nil; 155 | 156 | Check(TestDestroy = 0, 'Expected no deaths while keeping alive!'); 157 | 158 | Obj.Free; 159 | Check(TestDestroy = 3, 'Expected all objects to be killed!'); 160 | 161 | { ------------ Interfaces, Chain -------------} 162 | TestDestroy := 0; 163 | Obj := TTestRefCountedObject.Create(Self); 164 | Obj1 := TTestRefCountedObject.Create(Self); 165 | Obj2 := TTestRefCountedObject.Create(Self); 166 | 167 | I1 := Obj1; 168 | I2 := Obj2; 169 | 170 | { Should not allow Obj1 and 2 to be killed! } 171 | Obj.KeepObjectAlive(Obj1); 172 | Obj1.KeepObjectAlive(Obj2); 173 | 174 | I1 := nil; 175 | I2 := nil; 176 | 177 | Check(TestDestroy = 0, 'Expected no deaths while keeping alive!'); 178 | 179 | Obj.Free; 180 | Check(TestDestroy = 3, 'Expected all objects to be killed!'); 181 | 182 | { ------------ Test nil's ------------ } 183 | TestDestroy := 0; 184 | Obj := TTestRefCountedObject.Create(Self); 185 | 186 | Obj.KeepObjectAlive(nil); 187 | Obj.KeepObjectAlive(nil); 188 | Obj.KeepObjectAlive(nil); 189 | 190 | Obj.Free; 191 | 192 | Check(TestDestroy = 1, 'Expected Obj to die properly!'); 193 | end; 194 | 195 | procedure TTestBase.TestRefCountedObjectLife; 196 | var 197 | Obj: TTestRefCountedObject; 198 | I, I1: ICheck; 199 | begin 200 | { First types of checks } 201 | Obj := TTestRefCountedObject.Create(Self); 202 | Obj.CheckNotConstructing(); 203 | Obj.CheckRefCountEquals(0); 204 | Obj.Free; 205 | 206 | { Interface checks } 207 | I := TTestRefCountedObject.Create(Self); 208 | I.CheckNotConstructing(); 209 | I.CheckRefCountEquals(1); 210 | 211 | I1 := I; 212 | I.CheckRefCountEquals(2); 213 | 214 | I1 := nil; 215 | I.CheckRefCountEquals(1); 216 | 217 | I := nil; 218 | end; 219 | 220 | procedure TTestBase.TestRefCountedObjectReleaseObject; 221 | var 222 | Obj, Obj1, Obj2: TTestRefCountedObject; 223 | I1, I2: ICheck; 224 | begin 225 | { ------------ No Interfaces, No destroy ----------- } 226 | TestDestroy := 0; 227 | 228 | Obj := TTestRefCountedObject.Create(Self); 229 | Obj1 := TTestRefCountedObject.Create(Self); 230 | Obj2 := TTestRefCountedObject.Create(Self); 231 | 232 | { Register for keep-alive } 233 | Obj.KeepObjectAlive(Obj1); 234 | Obj.KeepObjectAlive(Obj2); 235 | 236 | Obj.ReleaseObject(Obj1); 237 | Obj.ReleaseObject(Obj2); 238 | 239 | Obj.Free; 240 | 241 | Check(TestDestroy = 1, 'Only Obj expected to be gone!'); 242 | 243 | { ------------ No Interfaces, Destroy ----------- } 244 | TestDestroy := 0; 245 | 246 | Obj := TTestRefCountedObject.Create(Self); 247 | 248 | { Register for keep-alive } 249 | Obj.KeepObjectAlive(Obj1); 250 | Obj.KeepObjectAlive(Obj2); 251 | 252 | Obj.ReleaseObject(Obj1, true); 253 | Obj.ReleaseObject(Obj2, true); 254 | 255 | Obj.Free; 256 | 257 | Check(TestDestroy = 3, 'Only Obj, Obj1, Obj2 expected to be gone!'); 258 | 259 | { ------------ Interfaces, Destroy ----------- } 260 | TestDestroy := 0; 261 | 262 | Obj := TTestRefCountedObject.Create(Self); 263 | Obj1 := TTestRefCountedObject.Create(Self); 264 | Obj2 := TTestRefCountedObject.Create(Self); 265 | 266 | I1 := Obj1; 267 | I2 := Obj2; 268 | 269 | { Register for keep-alive } 270 | Obj.KeepObjectAlive(Obj1); 271 | Obj.KeepObjectAlive(Obj2); 272 | 273 | I1 := nil; 274 | I2 := nil; 275 | 276 | Obj.ReleaseObject(Obj1); 277 | Obj.ReleaseObject(Obj2); 278 | 279 | Check(TestDestroy = 2, 'Only Obj1, Obj2 expected to be gone!'); 280 | 281 | Obj.Free; 282 | Check(TestDestroy = 3, 'All Obj, Obj1, Obj2 expected to be gone!'); 283 | 284 | { ------------ Lots of Interfaces, Destroy ----------- } 285 | TestDestroy := 0; 286 | 287 | Obj := TTestRefCountedObject.Create(Self); 288 | Obj1 := TTestRefCountedObject.Create(Self); 289 | Obj2 := TTestRefCountedObject.Create(Self); 290 | 291 | I1 := Obj1; 292 | I2 := Obj2; 293 | 294 | { Register for keep-alive } 295 | Obj.KeepObjectAlive(Obj1); 296 | Obj.KeepObjectAlive(Obj2); 297 | Obj.KeepObjectAlive(Obj1); 298 | Obj.KeepObjectAlive(Obj2); 299 | Obj.KeepObjectAlive(Obj1); 300 | Obj.KeepObjectAlive(Obj2); 301 | 302 | I1 := nil; 303 | I2 := nil; 304 | 305 | Obj.ReleaseObject(Obj1); 306 | Obj.ReleaseObject(Obj2); 307 | Check(TestDestroy = 0, 'Nothing should be gone!'); 308 | 309 | Obj.ReleaseObject(Obj1); 310 | Obj.ReleaseObject(Obj2); 311 | Check(TestDestroy = 0, 'Nothing should be gone!'); 312 | 313 | Obj.Free; 314 | Check(TestDestroy = 3, 'All Obj, Obj1, Obj2 expected to be gone!'); 315 | end; 316 | 317 | 318 | procedure TTestBase.TestRefCountedObjectExceptions; 319 | var 320 | Obj: TTestRefCountedObject; 321 | begin 322 | Obj := TTestRefCountedObject.Create(self); 323 | 324 | CheckException(ECannotSelfReferenceException, 325 | procedure() begin 326 | Obj.KeepObjectAlive(Obj); 327 | end, 328 | 'ECannotSelfReferenceException not thrown in KeepObjectAlive()' 329 | ); 330 | 331 | CheckException(ECannotSelfReferenceException, 332 | procedure() begin 333 | Obj.ReleaseObject(Obj); 334 | end, 335 | 'ECannotSelfReferenceException not thrown in ReleaseObject()' 336 | ); 337 | 338 | Obj.Free; 339 | end; 340 | 341 | procedure TTestBase.TestRefCountedObjectExtractReference; 342 | var 343 | Obj: TTestRefCountedObject; 344 | I: ICheck; 345 | begin 346 | Obj := TTestRefCountedObject.Create(Self); 347 | Check(Obj.ExtractReference = nil, 'Expected nil!'); 348 | 349 | I := Obj; 350 | Check(Obj.ExtractReference <> nil, 'Expected not nil!'); 351 | 352 | I := nil; 353 | end; 354 | 355 | { TTestRefCountedObject } 356 | 357 | procedure TTestRefCountedObject.CheckNotConstructing; 358 | begin 359 | FTest.Check(not Constructing, 'Should not be checked as Constructing!'); 360 | end; 361 | 362 | procedure TTestRefCountedObject.CheckRefCountEquals(const Cnt: Integer); 363 | begin 364 | FTest.Check(RefCount = Cnt, 'RefCount is not what it was expected to be!'); 365 | end; 366 | 367 | constructor TTestRefCountedObject.Create(const Test: TTestBase); 368 | begin 369 | Test.Check(Constructing, 'Should be checked as Constructing!'); 370 | Test.Check(RefCount = 1, 'Ref count should be 1'); 371 | Test.Check(ExtractReference = nil, 'No reference should be expected in ctor!'); 372 | 373 | FTest := Test; 374 | end; 375 | 376 | destructor TTestRefCountedObject.Destroy; 377 | begin 378 | FTest.Check(not Constructing, 'Should not be checked as Constructing!'); 379 | Inc(TestDestroy); 380 | 381 | inherited; 382 | end; 383 | 384 | { TTestRules } 385 | 386 | procedure TTestRules.Test_Create; 387 | var 388 | LStrRules: TRules; 389 | begin 390 | CheckException(EArgumentNilException, 391 | procedure() 392 | begin 393 | TRules.Create(nil, TEqualityComparer.Default) 394 | end, 395 | 'EArgumentNilException not thrown in TRules.Create (nil, xxx).' 396 | ); 397 | 398 | CheckException(EArgumentNilException, 399 | procedure() 400 | begin 401 | TRules.Create(TComparer.Default, nil) 402 | end, 403 | 'EArgumentNilException not thrown in TRules.Create (xxx, nil).' 404 | ); 405 | 406 | LStrRules := TRules.Create(TComparer.Default, StringCaseInsensitiveComparer); 407 | LStrRules := TRules.Create(StringCaseInsensitiveComparer, TEqualityComparer.Default); 408 | end; 409 | 410 | procedure TTestRules.Test_Custom; 411 | var 412 | LStrRules: TRules; 413 | begin 414 | CheckException(EArgumentNilException, 415 | procedure() 416 | begin 417 | TRules.Custom(nil) 418 | end, 419 | 'EArgumentNilException not thrown in TRules.Custom (nil).' 420 | ); 421 | 422 | LStrRules := TRules.Custom(StringCaseInsensitiveComparer); 423 | end; 424 | 425 | procedure TTestRules.Test_Default; 426 | var 427 | LStrRules: TRules; 428 | begin 429 | LStrRules := TRules.Default; 430 | end; 431 | 432 | { TInsensitiveStringComparer } 433 | 434 | function TInsensitiveStringComparer.Compare(const Left, Right: string): Integer; 435 | begin 436 | Result := CompareText(Left, Right); 437 | end; 438 | 439 | function TInsensitiveStringComparer.Equals(const Left, Right: string): Boolean; 440 | begin 441 | Result := SameText(Left, Right); 442 | end; 443 | 444 | function TInsensitiveStringComparer.GetHashCode(const Value: string): Integer; 445 | var 446 | Upped: string; 447 | begin 448 | Upped := AnsiUpperCase(Value); 449 | Result := BobJenkinsHash(PChar(Upped)^, SizeOf(Char) * Length(Upped), 0); 450 | end; 451 | 452 | 453 | initialization 454 | StringCaseInsensitiveComparer := TInsensitiveStringComparer.Create; 455 | 456 | RegisterTests('Internal.Support', [ 457 | TTestBase.Suite, 458 | TTestRules.Suite 459 | ]); 460 | 461 | finalization 462 | StringCaseInsensitiveComparer.Free; 463 | 464 | end. 465 | -------------------------------------------------------------------------------- /src/Tests/Tests.dpr: -------------------------------------------------------------------------------- 1 | program Tests; 2 | { 3 | 4 | Delphi DUnit Test Project 5 | ------------------------- 6 | This project contains the DUnit test framework and the GUI/Console test runners. 7 | Add "CONSOLE_TESTRUNNER" to the conditional defines entry in the project options 8 | to use the console test runner. Otherwise the GUI test runner will be used by 9 | default. 10 | 11 | } 12 | 13 | {$IFDEF CONSOLE_TESTRUNNER} 14 | {$APPTYPE CONSOLE} 15 | {$ENDIF} 16 | 17 | uses 18 | Forms, 19 | TestFramework, 20 | GUITestRunner, 21 | TextTestRunner, 22 | Tests.Conformance.Base in 'Tests.Conformance.Base.pas', 23 | Tests.Conformance.Lists in 'Tests.Conformance.Lists.pas', 24 | Tests.Conformance.Stacks in 'Tests.Conformance.Stacks.pas', 25 | Tests.Conformance.Queues in 'Tests.Conformance.Queues.pas', 26 | Tests.Conformance.Sets in 'Tests.Conformance.Sets.pas', 27 | Tests.Conformance.Dictionaries in 'Tests.Conformance.Dictionaries.pas', 28 | Tests.Conformance.BidiDictionaries in 'Tests.Conformance.BidiDictionaries.pas', 29 | Tests.Conformance.MultiMaps in 'Tests.Conformance.MultiMaps.pas', 30 | Tests.Conformance.BidiMaps in 'Tests.Conformance.BidiMaps.pas', 31 | Tests.Conformance.Bags in 'Tests.Conformance.Bags.pas', 32 | Tests.Internal.Basics in 'Tests.Internal.Basics.pas', 33 | Tests.Internal.Serialization in 'Tests.Internal.Serialization.pas', 34 | Tests.Internal.Dynamic in 'Tests.Internal.Dynamic.pas', 35 | Tests.Conformance.Specific in 'Tests.Conformance.Specific.pas'; 36 | 37 | {$R *.RES} 38 | 39 | 40 | begin 41 | Application.Initialize; 42 | 43 | if IsConsole then 44 | with TextTestRunner.RunRegisteredTests do 45 | Free 46 | else 47 | GUITestRunner.RunRegisteredTests; 48 | end. 49 | 50 | -------------------------------------------------------------------------------- /src/Tests/Tests.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {4C4B77A9-7747-4486-8269-5CF789422DAC} 4 | Tests.dpr 5 | 13.4 6 | True 7 | Debug 8 | Application 9 | VCL 10 | DCC32 11 | Win32 12 | 1 13 | Win32 14 | 15 | 16 | true 17 | 18 | 19 | true 20 | Base 21 | true 22 | 23 | 24 | true 25 | Cfg_1 26 | true 27 | true 28 | 29 | 30 | true 31 | Base 32 | true 33 | 34 | 35 | 1033 36 | true 37 | 48 38 | CompanyName=Alexandru Ciobanu;FileDescription=Collections Tests;FileVersion=1.2.0.48;InternalName=delphi-coll;LegalCopyright=Alexandru Ciobanu;LegalTrademarks=;OriginalFilename=;ProductName=Collections Tests;ProductVersion=1.2.0.0;Comments= 39 | Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 40 | 2 41 | true 42 | ..\..\bin\Tests.exe 43 | ..\..\bin 44 | vclx;vcl;rtl;vclimg;vcldb;dbrtl;adortl;DbxCommonDriver;dbexpress;dbxcds;xmlrtl;vclie;inet;IndyProtocols;ExpertsCreators;ExpertsUI;inetdbbde;inetdbxpress;vclactnband;vclribbon;soaprtl;dsnap;dsnapcon;websnap;webdsnap;inetdb;bdertl;vcldbx;IndySystem;IndyCore;DataSnapIndy10ServerTransport;DataSnapProviderClient;DbxClientDriver;DataSnapClient;DataSnapServer;DBXInterBaseDriver;DBXMySQLDriver;DBXFirebirdDriver;DBXSybaseASEDriver;DBXSybaseASADriver;DBXOracleDriver;DBXMSSQLDriver;DBXInformixDriver;DBXDb2Driver;AzureCloud;vcltouch;svnui;svn;CloudService;$(DCC_UsePackage) 45 | $(BDS)\Source\DUnit\src;$(DCC_UnitSearchPath) 46 | 00400000 47 | ..\..\bin 48 | _CONSOLE_TESTRUNNER;$(DCC_Define) 49 | ..\..\bin 50 | false 51 | false 52 | false 53 | false 54 | false 55 | 56 | 57 | DEBUG;$(DCC_Define) 58 | false 59 | true 60 | 61 | 62 | ..\..\bin;$(DCC_UnitSearchPath) 63 | 64 | 65 | false 66 | RELEASE;$(DCC_Define) 67 | 0 68 | false 69 | 70 | 71 | 72 | MainSource 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
$R *.RES
88 |
89 | 90 |
$R *.RES
91 |
92 | 93 | Cfg_2 94 | Base 95 | 96 | 97 | Base 98 | 99 | 100 | Cfg_1 101 | Base 102 | 103 |
104 | 105 | 106 | 107 | Delphi.Personality.12 108 | 109 | 110 | 111 | 112 | True 113 | False 114 | 1 115 | 0 116 | 4390 117 | 32767 118 | False 119 | False 120 | False 121 | False 122 | False 123 | 1033 124 | 1252 125 | 126 | 127 | 128 | 129 | 1.0.4390.32767 130 | 131 | 132 | 133 | 134 | 135 | 1.0.0.0 136 | 137 | 138 | 139 | Tests.dpr 140 | 141 | 142 | 143 | 144 | 145 | False 146 | True 147 | 148 | 149 | DUnit / Delphi Win32 150 | GUI 151 | D:\Projects\coll\src\Library\Collections.dproj 152 | 153 | 154 | 155 | 12 156 | 157 |
158 | -------------------------------------------------------------------------------- /src/Tests/Tests.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/src/Tests/Tests.res -------------------------------------------------------------------------------- /src/Tests/Tests_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/delphidabbler/delphi-coll-xe/f072f729a3d18b1ae8cfc7aca9ea1887a1b6e9f1/src/Tests/Tests_Icon.ico --------------------------------------------------------------------------------