lists.inc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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. Var
  103. OldPointer :Pointer;
  104. begin
  105. If (Index<0) or (Index>=FCount) then
  106. Error (SListIndexError,Index);
  107. FCount:=FCount-1;
  108. OldPointer:=Flist^[Index];
  109. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  110. // Shrink the list if appropiate
  111. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  112. begin
  113. FCapacity := FCapacity shr 1;
  114. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  115. end;
  116. If OldPointer<>nil then
  117. Notify(OldPointer,lnDeleted);
  118. end;
  119. class procedure TList.Error(const Msg: string; Data: Integer);
  120. begin
  121. {$ifdef VER1_0}
  122. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  123. {$else VER1_0}
  124. Raise EListError.CreateFmt(Msg,[Data]) at pointer(get_caller_addr(get_frame));
  125. {$endif VER1_0}
  126. end;
  127. procedure TList.Exchange(Index1, Index2: Integer);
  128. var Temp : Pointer;
  129. begin
  130. If ((Index1>=FCount) or (Index1<0)) then
  131. Error(SListIndexError,Index1);
  132. If ((Index2>=FCount) or (Index2<0)) then
  133. Error(SListIndexError,Index2);
  134. Temp:=FList^[Index1];
  135. FList^[Index1]:=FList^[Index2];
  136. FList^[Index2]:=Temp;
  137. end;
  138. function TList.Expand: TList;
  139. Var IncSize : Longint;
  140. begin
  141. if FCount<FCapacity then exit;
  142. IncSize:=4;
  143. if FCapacity>3 then IncSize:=IncSize+4;
  144. if FCapacity>8 then IncSize:=IncSize+8;
  145. if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
  146. SetCapacity(FCapacity+IncSize);
  147. Result:=Self;
  148. end;
  149. function TList.First: Pointer;
  150. begin
  151. If FCount=0 then
  152. Result:=Nil
  153. else
  154. Result:=Items[0];
  155. end;
  156. function TList.IndexOf(Item: Pointer): Integer;
  157. begin
  158. Result:=0;
  159. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  160. If Result=FCount then Result:=-1;
  161. end;
  162. procedure TList.Insert(Index: Integer; Item: Pointer);
  163. begin
  164. If (Index<0) or (Index>FCount )then
  165. Error(SlistIndexError,Index);
  166. IF FCount=FCapacity Then Self.Expand;
  167. If Index<FCount then
  168. System.Move (Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  169. FList^[Index]:=Item;
  170. FCount:=FCount+1;
  171. If Item<>NIl then
  172. Notify(Item,lnAdded);
  173. end;
  174. function TList.Last: Pointer;
  175. begin
  176. // Wouldn't it be better to return nil if the count is zero ?
  177. If FCount=0 then
  178. Result:=Nil
  179. else
  180. Result:=Items[FCount-1];
  181. end;
  182. procedure TList.Move(CurIndex, NewIndex: Integer);
  183. Var Temp : Pointer;
  184. begin
  185. If ((CurIndex<0) or (CurIndex>Count-1)) then
  186. Error(SListIndexError,CurIndex);
  187. If (NewINdex<0) then
  188. Error(SlistIndexError,NewIndex);
  189. Temp:=FList^[CurIndex];
  190. FList^[CurIndex]:=Nil;
  191. Self.Delete(CurIndex);
  192. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  193. // Newindex changes when deleting ??
  194. Self.Insert (NewIndex,Nil);
  195. FList^[NewIndex]:=Temp;
  196. end;
  197. function TList.Remove(Item: Pointer): Integer;
  198. begin
  199. Result:=IndexOf(Item);
  200. If Result<>-1 then
  201. Self.Delete (Result);
  202. end;
  203. Procedure TList.Pack;
  204. Var {Last,I,J,}Runner : Longint;
  205. begin
  206. // Not the fastest; but surely correct
  207. For Runner:=Fcount-1 downto 0 do
  208. if Items[Runner]=Nil then Self.Delete(Runner);
  209. { The following may be faster in case of large and defragmented lists
  210. If count=0 then exit;
  211. Runner:=0;I:=0;
  212. TheLast:=Count;
  213. while runner<count do
  214. begin
  215. // Find first Nil
  216. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  217. if Runner<Count do
  218. begin
  219. // Start searching for non-nil from last known nil+1
  220. if i<Runner then I:=Runner+1;
  221. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  222. // Start looking for last non-nil of block.
  223. J:=I+1;
  224. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  225. // Move block and zero out
  226. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  227. FillWord (Flist^[I],(J-I)*WordRatio,0);
  228. // Update Runner and Last to point behind last block
  229. TheLast:=Runner+(J-I);
  230. If J=Count then
  231. begin
  232. // Shortcut, when J=Count we checked all pointers
  233. Runner:=Count
  234. else
  235. begin
  236. Runner:=TheLast;
  237. I:=j;
  238. end;
  239. end;
  240. Count:=TheLast;
  241. }
  242. end;
  243. // Needed by Sort method.
  244. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  245. Compare : TListSortCompare);
  246. Var I,J : Longint;
  247. P,Q : Pointer;
  248. begin
  249. Repeat
  250. I:=L;
  251. J:=R;
  252. P:=FList^[ (L+R) div 2 ];
  253. repeat
  254. While Compare(P,FList^[i])>0 Do I:=I+1;
  255. While Compare(P,FList^[J])<0 Do J:=J-1;
  256. If I<=J then
  257. begin
  258. Q:=Flist^[I];
  259. Flist^[I]:=FList^[J];
  260. FList^[J]:=Q;
  261. I:=I+1;
  262. J:=j-1;
  263. end;
  264. Until I>J;
  265. If L<J then QuickSort (FList,L,J,Compare);
  266. L:=I;
  267. Until I>=R;
  268. end;
  269. procedure TList.Sort(Compare: TListSortCompare);
  270. begin
  271. If Not Assigned(FList) or (FCount<2) then exit;
  272. QuickSort (Flist, 0, FCount-1,Compare);
  273. end;
  274. {****************************************************************************}
  275. {* TThreadList *}
  276. {****************************************************************************}
  277. constructor TThreadList.Create;
  278. begin
  279. inherited Create;
  280. //InitializeCriticalSection(FLock);
  281. FList := TList.Create;
  282. end;
  283. destructor TThreadList.Destroy;
  284. begin
  285. LockList;
  286. try
  287. FList.Free;
  288. inherited Destroy;
  289. finally
  290. UnlockList;
  291. end;
  292. end;
  293. procedure TThreadList.Add(Item: Pointer);
  294. begin
  295. Locklist;
  296. try
  297. //make sure it's not already in the list
  298. if FList.indexof(Item) = -1 then
  299. FList.Add(Item);
  300. finally
  301. UnlockList;
  302. end;
  303. end;
  304. procedure TThreadList.Clear;
  305. begin
  306. Locklist;
  307. try
  308. FList.Clear;
  309. finally
  310. UnLockList;
  311. end;
  312. end;
  313. function TThreadList.LockList: TList;
  314. begin
  315. Result := FList;
  316. end;
  317. procedure TThreadList.Remove(Item: Pointer);
  318. begin
  319. LockList;
  320. try
  321. FList.Remove(Item);
  322. finally
  323. UnlockList;
  324. end;
  325. end;
  326. procedure TThreadList.UnlockList;
  327. begin
  328. end;
  329. {
  330. $Log$
  331. Revision 1.9 2002-09-07 15:15:24 peter
  332. * old logs removed and tabs fixed
  333. Revision 1.8 2002/08/16 10:04:58 michael
  334. + Notify correctly implemented
  335. Revision 1.7 2002/07/16 14:00:55 florian
  336. * raise takes now a void pointer as at and frame address
  337. instead of a longint, fixed
  338. }