| 1 |
unit listcoll; |
| 2 |
{$IFDEF FPC} |
| 3 |
{$MODE DELPHI}{$H-} |
| 4 |
{$ENDIF} |
| 5 |
|
| 6 |
(***************************************) |
| 7 |
(* Copyright (C) 2003, SHIRAISHI Kazuo *) |
| 8 |
(***************************************) |
| 9 |
|
| 10 |
|
| 11 |
interface |
| 12 |
|
| 13 |
uses Classes; |
| 14 |
|
| 15 |
type |
| 16 |
(* |
| 17 |
TForEachProc = procedure(O: TObject); |
| 18 |
TFirstLastFunc = function(O: TObject): Boolean; |
| 19 |
*) |
| 20 |
|
| 21 |
TListCollection = class(TList) |
| 22 |
public |
| 23 |
procedure clear(i:integer); |
| 24 |
{function at(index:integer):pointer;} |
| 25 |
procedure atDelete(index:integer); |
| 26 |
procedure atInsert(index:integer; item:pointer); |
| 27 |
procedure deleteall; |
| 28 |
procedure insert(item:pointer); |
| 29 |
procedure FreeItem(item:pointer);virtual; |
| 30 |
procedure FreeAll; |
| 31 |
destructor Destroy; override; |
| 32 |
(* |
| 33 |
procedure ForEach(Proc: TForEachProc); |
| 34 |
function FirstThat(TestFunc: TFirstLastFunc): TObject; |
| 35 |
function LastThat(TestFunc: TFirstLastFunc): TObject; |
| 36 |
*) |
| 37 |
end; |
| 38 |
|
| 39 |
TSortedListCollection = class(TListCollection) |
| 40 |
procedure insert(item:pointer); |
| 41 |
function search(key:pointer; var index:integer):boolean; |
| 42 |
function compare(key1,key2:pointer):integer;virtual;abstract; |
| 43 |
private |
| 44 |
function keyof(item:pointer):pointer; |
| 45 |
end; |
| 46 |
|
| 47 |
TStringCollection = Class(TSortedListCollection) |
| 48 |
function compare(key1,key2:pointer):integer;override; |
| 49 |
procedure freeitem(item:pointer);override; |
| 50 |
end; |
| 51 |
|
| 52 |
|
| 53 |
|
| 54 |
implementation |
| 55 |
|
| 56 |
type PString=^ShortString; |
| 57 |
function newStr(s:ShortString):PString;forward; |
| 58 |
procedure DisposeStr(p:PString);forward; |
| 59 |
|
| 60 |
procedure TListCollection.clear(i:integer); |
| 61 |
begin |
| 62 |
; |
| 63 |
end; |
| 64 |
|
| 65 |
{ |
| 66 |
function TListCollection.at(index:integer):pointer; |
| 67 |
begin |
| 68 |
result:=items[index] |
| 69 |
end; |
| 70 |
} |
| 71 |
|
| 72 |
procedure TListCollection.atDelete(index:integer); |
| 73 |
begin |
| 74 |
inherited delete(index); |
| 75 |
end; |
| 76 |
|
| 77 |
procedure TListCollection.atInsert(index:integer; item:pointer); |
| 78 |
begin |
| 79 |
inherited insert(index,item); |
| 80 |
end; |
| 81 |
|
| 82 |
procedure TListCollection.deleteAll; |
| 83 |
var |
| 84 |
i:integer; |
| 85 |
begin |
| 86 |
for i:=count-1 downto 0 do |
| 87 |
Delete(i); |
| 88 |
(* |
| 89 |
while count>0 do |
| 90 |
begin |
| 91 |
Delete(0); { Free item from list } |
| 92 |
end; { until out of items } |
| 93 |
*) |
| 94 |
end; |
| 95 |
|
| 96 |
procedure TListCollection.insert(item:pointer); |
| 97 |
begin |
| 98 |
inherited add(item) |
| 99 |
end; |
| 100 |
|
| 101 |
procedure TListCollection.FreeItem(item:pointer); |
| 102 |
begin |
| 103 |
if item<>nil then (TObject(item) as TObject).Free; |
| 104 |
end; |
| 105 |
|
| 106 |
procedure TListCollection.FreeAll; |
| 107 |
var |
| 108 |
Temp: pointer; |
| 109 |
i:integer; |
| 110 |
begin |
| 111 |
for i:=count-1 downto 0 do |
| 112 |
begin |
| 113 |
Temp := Items[i]; |
| 114 |
FreeItem(Temp); { Delete Item } |
| 115 |
Delete(i); { Free item from list } |
| 116 |
end; |
| 117 |
|
| 118 |
(* |
| 119 |
while count>0 do |
| 120 |
begin |
| 121 |
Temp := Items[0]; |
| 122 |
FreeItem(Temp); { Delete Item } |
| 123 |
Delete(0); { Free item from list } |
| 124 |
end; |
| 125 |
{ until out of items } |
| 126 |
*) |
| 127 |
end; |
| 128 |
|
| 129 |
|
| 130 |
|
| 131 |
destructor TListCollection.Destroy; |
| 132 |
begin |
| 133 |
FreeAll; |
| 134 |
inherited Destroy; { call the inherited } |
| 135 |
end; |
| 136 |
|
| 137 |
function TSortedListCollection.search(key:pointer; var index:integer):boolean; |
| 138 |
begin |
| 139 |
index:=0; |
| 140 |
while (index<count) and (compare(key,items[index])<0) do |
| 141 |
inc(index); |
| 142 |
search:=(index<count) and (compare(key,items[index])=0) |
| 143 |
end; |
| 144 |
|
| 145 |
function TSortedListCollection.keyof(item:pointer):pointer; |
| 146 |
begin |
| 147 |
keyof:=item |
| 148 |
end; |
| 149 |
|
| 150 |
procedure TSortedListCollection.insert(item:pointer); |
| 151 |
var |
| 152 |
index:integer; |
| 153 |
begin |
| 154 |
if not search(KeyOf(item),index) then |
| 155 |
atInsert(index,item) |
| 156 |
//else |
| 157 |
// index:=0 |
| 158 |
end; |
| 159 |
|
| 160 |
|
| 161 |
function TStringCollection.compare(key1,key2:pointer):integer; |
| 162 |
begin |
| 163 |
if key1=nil then |
| 164 |
if key2=nil then |
| 165 |
compare:=0 |
| 166 |
else |
| 167 |
compare:=-1 |
| 168 |
else if key2=nil then compare :=1 |
| 169 |
else if PString(key1)^<PString(key2)^ then compare:=-1 |
| 170 |
else if PString(key1)^=PString(key2)^ then compare:=0 |
| 171 |
else compare:=1 |
| 172 |
end; |
| 173 |
|
| 174 |
procedure TStringCollection.freeitem(item:pointer); |
| 175 |
begin |
| 176 |
DisposeStr(PString(item)) |
| 177 |
end; |
| 178 |
|
| 179 |
|
| 180 |
function newStr(s:ShortString):PString; |
| 181 |
begin |
| 182 |
if length(s)>0 then |
| 183 |
begin |
| 184 |
GetMem(Result,Length(s)+1); |
| 185 |
Result^:=s |
| 186 |
end |
| 187 |
else |
| 188 |
result:=nil |
| 189 |
end; |
| 190 |
|
| 191 |
procedure DisposeStr(p:PString); |
| 192 |
begin |
| 193 |
if p<>nil then FreeMem(p,length(PString(p)^)+1); |
| 194 |
end; |
| 195 |
|
| 196 |
(* |
| 197 |
procedure TListCollection.ForEach(Proc: TForEachProc); |
| 198 |
var |
| 199 |
i: integer; |
| 200 |
begin |
| 201 |
for i := 0 to Count - 1 do { iterate throught the list } |
| 202 |
Proc(Items[i]); { call proc and pass each item } |
| 203 |
end; |
| 204 |
|
| 205 |
function TListCollection.FirstThat(TestFunc: TFirstLastFunc): TObject; |
| 206 |
var |
| 207 |
Func: TFirstLastFunc; |
| 208 |
i: integer; |
| 209 |
begin |
| 210 |
for i := 0 to Count - 1 do { iterate throught the list } |
| 211 |
if TestFunc(Items[i]) then begin { call TestFunc and pass each item } |
| 212 |
Result := Items[i]; { return the first match } |
| 213 |
Break; |
| 214 |
end; |
| 215 |
end; |
| 216 |
|
| 217 |
function TListCollection.LastThat(TestFunc: TFirstLastFunc): TObject; |
| 218 |
var |
| 219 |
i: integer; |
| 220 |
begin |
| 221 |
for i := Count - 1 downto 0 do { iterate backward through the list } |
| 222 |
if TestFunc(Items[i]) then begin { call TestFunc and pass each item } |
| 223 |
Result := Items[i]; { return the first match } |
| 224 |
Break; |
| 225 |
end; |
| 226 |
end; |
| 227 |
*) |
| 228 |
|
| 229 |
end. |