lists.inc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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 longint(get_caller_addr(get_frame));
  123. {$else VER1_0}
  124. Raise EListError.CreateFmt(Msg,[Data]) at 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. procedure TList.Assign(Obj:TList);
  275. // Principle copied from TCollection
  276. var i : Integer;
  277. begin
  278. Clear;
  279. For I:=0 To Obj.Count-1 Do
  280. Add(Obj[i]);
  281. end;
  282. {****************************************************************************}
  283. {* TThreadList *}
  284. {****************************************************************************}
  285. constructor TThreadList.Create;
  286. begin
  287. inherited Create;
  288. //InitializeCriticalSection(FLock);
  289. FList := TList.Create;
  290. end;
  291. destructor TThreadList.Destroy;
  292. begin
  293. LockList;
  294. try
  295. FList.Free;
  296. inherited Destroy;
  297. finally
  298. UnlockList;
  299. end;
  300. end;
  301. procedure TThreadList.Add(Item: Pointer);
  302. begin
  303. Locklist;
  304. try
  305. //make sure it's not already in the list
  306. if FList.indexof(Item) = -1 then
  307. FList.Add(Item);
  308. finally
  309. UnlockList;
  310. end;
  311. end;
  312. procedure TThreadList.Clear;
  313. begin
  314. Locklist;
  315. try
  316. FList.Clear;
  317. finally
  318. UnLockList;
  319. end;
  320. end;
  321. function TThreadList.LockList: TList;
  322. begin
  323. Result := FList;
  324. end;
  325. procedure TThreadList.Remove(Item: Pointer);
  326. begin
  327. LockList;
  328. try
  329. FList.Remove(Item);
  330. finally
  331. UnlockList;
  332. end;
  333. end;
  334. procedure TThreadList.UnlockList;
  335. begin
  336. end;
  337. {
  338. $Log$
  339. Revision 1.2 2003-10-07 14:30:57 marco
  340. * 1.0 version of assign
  341. Revision 1.1 2003/10/06 20:33:58 peter
  342. * classes moved to rtl for 1.1
  343. * classes .inc and classes.pp files moved to fcl/classes for
  344. backwards 1.0.x compatiblity to have it in the fcl
  345. Revision 1.9 2002/09/07 15:15:24 peter
  346. * old logs removed and tabs fixed
  347. Revision 1.8 2002/08/16 10:04:58 michael
  348. + Notify correctly implemented
  349. Revision 1.7 2002/07/16 14:00:55 florian
  350. * raise takes now a void pointer as at and frame address
  351. instead of a longint, fixed
  352. }