lists.inc 8.7 KB

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