lists.inc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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. if NewCapacity > FCapacity then
  65. FillChar (FList^ [FCapacity],
  66. (NewCapacity - FCapacity) * SizeOf (pointer), 0);
  67. FCapacity:=NewCapacity;
  68. end;
  69. procedure TList.SetCount(NewCount: Integer);
  70. begin
  71. If (NewCount<0) or (NewCount>MaxListSize)then
  72. Error(SListCountError,NewCount);
  73. If NewCount<FCount then
  74. FCount:=NewCount
  75. else If NewCount>FCount then
  76. begin
  77. If NewCount>FCapacity then
  78. SetCapacity (NewCount);
  79. If FCount<NewCount then
  80. FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
  81. FCount:=Newcount;
  82. end;
  83. end;
  84. destructor TList.Destroy;
  85. begin
  86. Self.Clear;
  87. inherited Destroy;
  88. end;
  89. Function TList.Add(Item: Pointer): Integer;
  90. begin
  91. Self.Insert (Count,Item);
  92. Result:=Count-1;
  93. end;
  94. Procedure TList.Clear;
  95. begin
  96. If Assigned(FList) then
  97. begin
  98. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  99. FList:=Nil;
  100. FCapacity:=0;
  101. FCount:=0;
  102. end;
  103. end;
  104. Procedure TList.Delete(Index: Integer);
  105. Var
  106. OldPointer :Pointer;
  107. begin
  108. If (Index<0) or (Index>=FCount) then
  109. Error (SListIndexError,Index);
  110. FCount:=FCount-1;
  111. OldPointer:=Flist^[Index];
  112. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  113. // Shrink the list if appropiate
  114. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  115. begin
  116. FCapacity := FCapacity shr 1;
  117. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  118. end;
  119. If OldPointer<>nil then
  120. Notify(OldPointer,lnDeleted);
  121. end;
  122. class procedure TList.Error(const Msg: string; Data: Integer);
  123. begin
  124. {$ifdef VER1_0}
  125. Raise EListError.CreateFmt(Msg,[Data]) at longint(get_caller_addr(get_frame));
  126. {$else VER1_0}
  127. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  128. {$endif VER1_0}
  129. end;
  130. procedure TList.Exchange(Index1, Index2: Integer);
  131. var Temp : Pointer;
  132. begin
  133. If ((Index1>=FCount) or (Index1<0)) then
  134. Error(SListIndexError,Index1);
  135. If ((Index2>=FCount) or (Index2<0)) then
  136. Error(SListIndexError,Index2);
  137. Temp:=FList^[Index1];
  138. FList^[Index1]:=FList^[Index2];
  139. FList^[Index2]:=Temp;
  140. end;
  141. function TList.Expand: TList;
  142. Var IncSize : Longint;
  143. begin
  144. if FCount<FCapacity then exit;
  145. IncSize:=4;
  146. if FCapacity>3 then IncSize:=IncSize+4;
  147. if FCapacity>8 then IncSize:=IncSize+8;
  148. if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
  149. SetCapacity(FCapacity+IncSize);
  150. Result:=Self;
  151. end;
  152. function TList.First: Pointer;
  153. begin
  154. If FCount=0 then
  155. Result:=Nil
  156. else
  157. Result:=Items[0];
  158. end;
  159. function TList.IndexOf(Item: Pointer): Integer;
  160. begin
  161. Result:=0;
  162. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  163. If Result=FCount then Result:=-1;
  164. end;
  165. procedure TList.Insert(Index: Integer; Item: Pointer);
  166. begin
  167. If (Index<0) or (Index>FCount )then
  168. Error(SlistIndexError,Index);
  169. IF FCount=FCapacity Then Self.Expand;
  170. If Index<FCount then
  171. System.Move (Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  172. FList^[Index]:=Item;
  173. FCount:=FCount+1;
  174. If Item<>NIl then
  175. Notify(Item,lnAdded);
  176. end;
  177. function TList.Last: Pointer;
  178. begin
  179. // Wouldn't it be better to return nil if the count is zero ?
  180. If FCount=0 then
  181. Result:=Nil
  182. else
  183. Result:=Items[FCount-1];
  184. end;
  185. procedure TList.Move(CurIndex, NewIndex: Integer);
  186. Var Temp : Pointer;
  187. begin
  188. If ((CurIndex<0) or (CurIndex>Count-1)) then
  189. Error(SListIndexError,CurIndex);
  190. If (NewINdex<0) then
  191. Error(SlistIndexError,NewIndex);
  192. Temp:=FList^[CurIndex];
  193. FList^[CurIndex]:=Nil;
  194. Self.Delete(CurIndex);
  195. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  196. // Newindex changes when deleting ??
  197. Self.Insert (NewIndex,Nil);
  198. FList^[NewIndex]:=Temp;
  199. end;
  200. function TList.Remove(Item: Pointer): Integer;
  201. begin
  202. Result:=IndexOf(Item);
  203. If Result<>-1 then
  204. Self.Delete (Result);
  205. end;
  206. Procedure TList.Pack;
  207. Var {Last,I,J,}Runner : Longint;
  208. begin
  209. // Not the fastest; but surely correct
  210. For Runner:=Fcount-1 downto 0 do
  211. if Items[Runner]=Nil then Self.Delete(Runner);
  212. { The following may be faster in case of large and defragmented lists
  213. If count=0 then exit;
  214. Runner:=0;I:=0;
  215. TheLast:=Count;
  216. while runner<count do
  217. begin
  218. // Find first Nil
  219. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  220. if Runner<Count do
  221. begin
  222. // Start searching for non-nil from last known nil+1
  223. if i<Runner then I:=Runner+1;
  224. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  225. // Start looking for last non-nil of block.
  226. J:=I+1;
  227. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  228. // Move block and zero out
  229. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  230. FillWord (Flist^[I],(J-I)*WordRatio,0);
  231. // Update Runner and Last to point behind last block
  232. TheLast:=Runner+(J-I);
  233. If J=Count then
  234. begin
  235. // Shortcut, when J=Count we checked all pointers
  236. Runner:=Count
  237. else
  238. begin
  239. Runner:=TheLast;
  240. I:=j;
  241. end;
  242. end;
  243. Count:=TheLast;
  244. }
  245. end;
  246. // Needed by Sort method.
  247. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  248. Compare : TListSortCompare);
  249. Var I,J : Longint;
  250. P,Q : Pointer;
  251. begin
  252. Repeat
  253. I:=L;
  254. J:=R;
  255. P:=FList^[ (L+R) div 2 ];
  256. repeat
  257. While Compare(P,FList^[i])>0 Do I:=I+1;
  258. While Compare(P,FList^[J])<0 Do J:=J-1;
  259. If I<=J then
  260. begin
  261. Q:=Flist^[I];
  262. Flist^[I]:=FList^[J];
  263. FList^[J]:=Q;
  264. I:=I+1;
  265. J:=j-1;
  266. end;
  267. Until I>J;
  268. If L<J then QuickSort (FList,L,J,Compare);
  269. L:=I;
  270. Until I>=R;
  271. end;
  272. procedure TList.Sort(Compare: TListSortCompare);
  273. begin
  274. If Not Assigned(FList) or (FCount<2) then exit;
  275. QuickSort (Flist, 0, FCount-1,Compare);
  276. end;
  277. procedure TList.Assign(Obj:TList);
  278. // Principle copied from TCollection
  279. var i : Integer;
  280. begin
  281. Clear;
  282. For I:=0 To Obj.Count-1 Do
  283. Add(Obj[i]);
  284. end;
  285. {****************************************************************************}
  286. {* TThreadList *}
  287. {****************************************************************************}
  288. constructor TThreadList.Create;
  289. begin
  290. inherited Create;
  291. //InitializeCriticalSection(FLock);
  292. FList := TList.Create;
  293. end;
  294. destructor TThreadList.Destroy;
  295. begin
  296. LockList;
  297. try
  298. FList.Free;
  299. inherited Destroy;
  300. finally
  301. UnlockList;
  302. end;
  303. end;
  304. procedure TThreadList.Add(Item: Pointer);
  305. begin
  306. Locklist;
  307. try
  308. //make sure it's not already in the list
  309. if FList.indexof(Item) = -1 then
  310. FList.Add(Item);
  311. finally
  312. UnlockList;
  313. end;
  314. end;
  315. procedure TThreadList.Clear;
  316. begin
  317. Locklist;
  318. try
  319. FList.Clear;
  320. finally
  321. UnLockList;
  322. end;
  323. end;
  324. function TThreadList.LockList: TList;
  325. begin
  326. Result := FList;
  327. end;
  328. procedure TThreadList.Remove(Item: Pointer);
  329. begin
  330. LockList;
  331. try
  332. FList.Remove(Item);
  333. finally
  334. UnlockList;
  335. end;
  336. end;
  337. procedure TThreadList.UnlockList;
  338. begin
  339. end;
  340. {
  341. $Log$
  342. Revision 1.4 2005-05-12 21:47:34 hajny
  343. * fix for SIGSEGV due to access to uninitialized pointers in TList
  344. Revision 1.3 2005/02/14 17:13:11 peter
  345. * truncate log
  346. }