lists.inc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************}
  12. {* TList *}
  13. {****************************************************************************}
  14. { TList = class(TObject)
  15. private
  16. FList: PPointerList;
  17. FCount: Integer;
  18. FCapacity: Integer;
  19. }
  20. Const
  21. // Ratio of Pointer and Word Size.
  22. WordRatio = SizeOf(Pointer) Div SizeOf(Word);
  23. function TList.Get(Index: Integer): Pointer;
  24. begin
  25. If (Index<0) or (Index>=FCount) then
  26. Error(SListIndexError,Index);
  27. Result:=FList^[Index];
  28. end;
  29. procedure TList.Grow;
  30. begin
  31. // Only for compatibility with Delphi. Not needed.
  32. end;
  33. procedure TList.Put(Index: Integer; Item: Pointer);
  34. begin
  35. if (Index<0) or (Index>=FCount) then
  36. Error(SListIndexError,Index);
  37. Flist^[Index]:=Item;
  38. end;
  39. procedure TList.SetCapacity(NewCapacity: Integer);
  40. Var NewList,ToFree : PPointerList;
  41. begin
  42. If (NewCapacity<0) or (NewCapacity>MaxListSize) then
  43. Error (SListCapacityError,NewCapacity);
  44. if NewCapacity=FCapacity then
  45. exit;
  46. ReallocMem(FList,SizeOf(Pointer)*NewCapacity);
  47. FCapacity:=NewCapacity;
  48. end;
  49. procedure TList.SetCount(NewCount: Integer);
  50. begin
  51. If (NewCount<0) or (NewCount>MaxListSize)then
  52. Error(SListCountError,NewCount);
  53. If NewCount<FCount then
  54. FCount:=NewCount
  55. else If NewCount>FCount then
  56. begin
  57. If NewCount>FCapacity then
  58. SetCapacity (NewCount);
  59. If FCount<NewCount then
  60. FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
  61. FCount:=Newcount;
  62. end;
  63. end;
  64. destructor TList.Destroy;
  65. begin
  66. Self.Clear;
  67. inherited Destroy;
  68. end;
  69. Function TList.Add(Item: Pointer): Integer;
  70. begin
  71. Self.Insert (Count,Item);
  72. Result:=Count-1;
  73. end;
  74. Procedure TList.Clear;
  75. begin
  76. If Assigned(FList) then
  77. begin
  78. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  79. FList:=Nil;
  80. FCapacity:=0;
  81. FCount:=0;
  82. end;
  83. end;
  84. Procedure TList.Delete(Index: Integer);
  85. begin
  86. If (Index<0) or (Index>=FCount) then
  87. Error (SListIndexError,Index);
  88. FCount:=FCount-1;
  89. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  90. // Shrink the list if appropiate
  91. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  92. begin
  93. FCapacity := FCapacity shr 1;
  94. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  95. end;
  96. end;
  97. class procedure TList.Error(const Msg: string; Data: Integer);
  98. begin
  99. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  100. end;
  101. procedure TList.Exchange(Index1, Index2: Integer);
  102. var Temp : Pointer;
  103. begin
  104. If ((Index1>=FCount) or (Index1<0)) then
  105. Error(SListIndexError,Index1);
  106. If ((Index2>=FCount) or (Index2<0)) then
  107. Error(SListIndexError,Index2);
  108. Temp:=FList^[Index1];
  109. FList^[Index1]:=FList^[Index2];
  110. FList^[Index2]:=Temp;
  111. end;
  112. function TList.Expand: TList;
  113. Var IncSize : Longint;
  114. begin
  115. if FCount<FCapacity then exit;
  116. IncSize:=4;
  117. if FCapacity>3 then IncSize:=IncSize+4;
  118. if FCapacity>8 then IncSize:=IncSize+8;
  119. if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
  120. SetCapacity(FCapacity+IncSize);
  121. Result:=Self;
  122. end;
  123. function TList.First: Pointer;
  124. begin
  125. If FCount=0 then
  126. Result:=Nil
  127. else
  128. Result:=Items[0];
  129. end;
  130. function TList.IndexOf(Item: Pointer): Integer;
  131. begin
  132. Result:=0;
  133. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  134. If Result=FCount then Result:=-1;
  135. end;
  136. procedure TList.Insert(Index: Integer; Item: Pointer);
  137. begin
  138. If (Index<0) or (Index>FCount )then
  139. Error(SlistIndexError,Index);
  140. IF FCount=FCapacity Then Self.Expand;
  141. If Index<FCount then
  142. System.Move (Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  143. FList^[Index]:=Item;
  144. FCount:=FCount+1;
  145. end;
  146. function TList.Last: Pointer;
  147. begin
  148. // Wouldn't it be better to return nil if the count is zero ?
  149. If FCount=0 then
  150. Result:=Nil
  151. else
  152. Result:=Items[FCount-1];
  153. end;
  154. procedure TList.Move(CurIndex, NewIndex: Integer);
  155. Var Temp : Pointer;
  156. begin
  157. If ((CurIndex<0) or (CurIndex>Count-1)) then
  158. Error(SListIndexError,CurIndex);
  159. If (NewINdex<0) then
  160. Error(SlistIndexError,NewIndex);
  161. Temp:=FList^[CurIndex];
  162. Self.Delete(CurIndex);
  163. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  164. // Newindex changes when deleting ??
  165. Self.Insert (NewIndex,Temp);
  166. end;
  167. function TList.Remove(Item: Pointer): Integer;
  168. begin
  169. Result:=IndexOf(Item);
  170. If Result<>-1 then
  171. Self.Delete (Result);
  172. end;
  173. Procedure TList.Pack;
  174. Var {Last,I,J,}Runner : Longint;
  175. begin
  176. // Not the fastest; but surely correct
  177. For Runner:=Fcount-1 downto 0 do
  178. if Items[Runner]=Nil then Self.Delete(Runner);
  179. { The following may be faster in case of large and defragmented lists
  180. If count=0 then exit;
  181. Runner:=0;I:=0;
  182. TheLast:=Count;
  183. while runner<count do
  184. begin
  185. // Find first Nil
  186. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  187. if Runner<Count do
  188. begin
  189. // Start searching for non-nil from last known nil+1
  190. if i<Runner then I:=Runner+1;
  191. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  192. // Start looking for last non-nil of block.
  193. J:=I+1;
  194. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  195. // Move block and zero out
  196. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  197. FillWord (Flist^[I],(J-I)*WordRatio,0);
  198. // Update Runner and Last to point behind last block
  199. TheLast:=Runner+(J-I);
  200. If J=Count then
  201. begin
  202. // Shortcut, when J=Count we checked all pointers
  203. Runner:=Count
  204. else
  205. begin
  206. Runner:=TheLast;
  207. I:=j;
  208. end;
  209. end;
  210. Count:=TheLast;
  211. }
  212. end;
  213. // Needed by Sort method.
  214. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  215. Compare : TListSortCompare);
  216. Var I,J : Longint;
  217. P,Q : Pointer;
  218. begin
  219. Repeat
  220. I:=L;
  221. J:=R;
  222. P:=FList^[ (L+R) div 2 ];
  223. repeat
  224. While Compare(P,FList^[i])>0 Do I:=I+1;
  225. While Compare(P,FList^[J])<0 Do J:=J-1;
  226. If I<=J then
  227. begin
  228. Q:=Flist^[I];
  229. Flist^[I]:=FList^[J];
  230. FList^[J]:=Q;
  231. I:=I+1;
  232. J:=j-1;
  233. end;
  234. Until I>J;
  235. If L<J then QuickSort (FList,L,J,Compare);
  236. L:=I;
  237. Until I>=R;
  238. end;
  239. procedure TList.Sort(Compare: TListSortCompare);
  240. begin
  241. If Not Assigned(FList) or (FCount<2) then exit;
  242. QuickSort (Flist, 0, FCount-1,Compare);
  243. end;
  244. {****************************************************************************}
  245. {* TThreadList *}
  246. {****************************************************************************}
  247. constructor TThreadList.Create;
  248. begin
  249. inherited Create;
  250. //InitializeCriticalSection(FLock);
  251. FList := TList.Create;
  252. end;
  253. destructor TThreadList.Destroy;
  254. begin
  255. LockList;
  256. try
  257. FList.Free;
  258. inherited Destroy;
  259. finally
  260. UnlockList;
  261. end;
  262. end;
  263. procedure TThreadList.Add(Item: Pointer);
  264. begin
  265. Locklist;
  266. try
  267. //make sure it's not already in the list
  268. if FList.indexof(Item) = -1 then
  269. FList.Add(Item);
  270. finally
  271. UnlockList;
  272. end;
  273. end;
  274. procedure TThreadList.Clear;
  275. begin
  276. Locklist;
  277. try
  278. FList.Clear;
  279. finally
  280. UnLockList;
  281. end;
  282. end;
  283. function TThreadList.LockList: TList;
  284. begin
  285. Result := FList;
  286. end;
  287. procedure TThreadList.Remove(Item: Pointer);
  288. begin
  289. LockList;
  290. try
  291. FList.Remove(Item);
  292. finally
  293. UnlockList;
  294. end;
  295. end;
  296. procedure TThreadList.UnlockList;
  297. begin
  298. end;
  299. {
  300. $Log$
  301. Revision 1.5 2001-07-17 22:07:29 sg
  302. * Added performance improvements suggested by Mattias Gaertner
  303. - list grows in steps of 25% if size >= 128
  304. - list shrinks by 50% if size drops below a quarter of the capacity
  305. Revision 1.4 2000/11/17 13:39:49 sg
  306. * Extended Error methods so that exceptions are raised from the caller's
  307. address instead of the Error method
  308. Revision 1.3 2000/09/14 18:39:31 michael
  309. + Fixed setcapacity
  310. Revision 1.2 2000/07/13 11:32:59 michael
  311. + removed logs
  312. }