lists.inc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. end;
  91. class procedure TList.Error(const Msg: string; Data: Integer);
  92. begin
  93. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  94. end;
  95. procedure TList.Exchange(Index1, Index2: Integer);
  96. var Temp : Pointer;
  97. begin
  98. If ((Index1>=FCount) or (Index1<0)) then
  99. Error(SListIndexError,Index1);
  100. If ((Index2>=FCount) or (Index2<0)) then
  101. Error(SListIndexError,Index2);
  102. Temp:=FList^[Index1];
  103. FList^[Index1]:=FList^[Index2];
  104. FList^[Index2]:=Temp;
  105. end;
  106. function TList.Expand: TList;
  107. Var IncSize : Longint;
  108. begin
  109. if FCount<FCapacity then exit;
  110. IncSize:=4;
  111. if FCapacity>3 then IncSize:=IncSize+4;
  112. if FCapacity>8 then IncSize:=IncSize+8;
  113. SetCapacity(FCapacity+IncSize);
  114. Result:=Self;
  115. end;
  116. function TList.First: Pointer;
  117. begin
  118. If FCount=0 then
  119. Result:=Nil
  120. else
  121. Result:=Items[0];
  122. end;
  123. function TList.IndexOf(Item: Pointer): Integer;
  124. begin
  125. Result:=0;
  126. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  127. If Result=FCount then Result:=-1;
  128. end;
  129. procedure TList.Insert(Index: Integer; Item: Pointer);
  130. begin
  131. If (Index<0) or (Index>FCount )then
  132. Error(SlistIndexError,Index);
  133. IF FCount=FCapacity Then Self.Expand;
  134. If Index<FCount then
  135. System.Move (Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  136. FList^[Index]:=Item;
  137. FCount:=FCount+1;
  138. end;
  139. function TList.Last: Pointer;
  140. begin
  141. // Wouldn't it be better to return nil if the count is zero ?
  142. If FCount=0 then
  143. Result:=Nil
  144. else
  145. Result:=Items[FCount-1];
  146. end;
  147. procedure TList.Move(CurIndex, NewIndex: Integer);
  148. Var Temp : Pointer;
  149. begin
  150. If ((CurIndex<0) or (CurIndex>Count-1)) then
  151. Error(SListIndexError,CurIndex);
  152. If (NewINdex<0) then
  153. Error(SlistIndexError,NewIndex);
  154. Temp:=FList^[CurIndex];
  155. Self.Delete(CurIndex);
  156. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  157. // Newindex changes when deleting ??
  158. Self.Insert (NewIndex,Temp);
  159. end;
  160. function TList.Remove(Item: Pointer): Integer;
  161. begin
  162. Result:=IndexOf(Item);
  163. If Result<>-1 then
  164. Self.Delete (Result);
  165. end;
  166. Procedure TList.Pack;
  167. Var {Last,I,J,}Runner : Longint;
  168. begin
  169. // Not the fastest; but surely correct
  170. For Runner:=Fcount-1 downto 0 do
  171. if Items[Runner]=Nil then Self.Delete(Runner);
  172. { The following may be faster in case of large and defragmented lists
  173. If count=0 then exit;
  174. Runner:=0;I:=0;
  175. TheLast:=Count;
  176. while runner<count do
  177. begin
  178. // Find first Nil
  179. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  180. if Runner<Count do
  181. begin
  182. // Start searching for non-nil from last known nil+1
  183. if i<Runner then I:=Runner+1;
  184. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  185. // Start looking for last non-nil of block.
  186. J:=I+1;
  187. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  188. // Move block and zero out
  189. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  190. FillWord (Flist^[I],(J-I)*WordRatio,0);
  191. // Update Runner and Last to point behind last block
  192. TheLast:=Runner+(J-I);
  193. If J=Count then
  194. begin
  195. // Shortcut, when J=Count we checked all pointers
  196. Runner:=Count
  197. else
  198. begin
  199. Runner:=TheLast;
  200. I:=j;
  201. end;
  202. end;
  203. Count:=TheLast;
  204. }
  205. end;
  206. // Needed by Sort method.
  207. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  208. Compare : TListSortCompare);
  209. Var I,J : Longint;
  210. P,Q : Pointer;
  211. begin
  212. Repeat
  213. I:=L;
  214. J:=R;
  215. P:=FList^[ (L+R) div 2 ];
  216. repeat
  217. While Compare(P,FList^[i])>0 Do I:=I+1;
  218. While Compare(P,FList^[J])<0 Do J:=J-1;
  219. If I<=J then
  220. begin
  221. Q:=Flist^[I];
  222. Flist^[I]:=FList^[J];
  223. FList^[J]:=Q;
  224. I:=I+1;
  225. J:=j-1;
  226. end;
  227. Until I>J;
  228. If L<J then QuickSort (FList,L,J,Compare);
  229. L:=I;
  230. Until I>=R;
  231. end;
  232. procedure TList.Sort(Compare: TListSortCompare);
  233. begin
  234. If Not Assigned(FList) or (FCount<2) then exit;
  235. QuickSort (Flist, 0, FCount-1,Compare);
  236. end;
  237. {****************************************************************************}
  238. {* TThreadList *}
  239. {****************************************************************************}
  240. constructor TThreadList.Create;
  241. begin
  242. inherited Create;
  243. //InitializeCriticalSection(FLock);
  244. FList := TList.Create;
  245. end;
  246. destructor TThreadList.Destroy;
  247. begin
  248. LockList;
  249. try
  250. FList.Free;
  251. inherited Destroy;
  252. finally
  253. UnlockList;
  254. end;
  255. end;
  256. procedure TThreadList.Add(Item: Pointer);
  257. begin
  258. Locklist;
  259. try
  260. //make sure it's not already in the list
  261. if FList.indexof(Item) = -1 then
  262. FList.Add(Item);
  263. finally
  264. UnlockList;
  265. end;
  266. end;
  267. procedure TThreadList.Clear;
  268. begin
  269. Locklist;
  270. try
  271. FList.Clear;
  272. finally
  273. UnLockList;
  274. end;
  275. end;
  276. function TThreadList.LockList: TList;
  277. begin
  278. Result := FList;
  279. end;
  280. procedure TThreadList.Remove(Item: Pointer);
  281. begin
  282. LockList;
  283. try
  284. FList.Remove(Item);
  285. finally
  286. UnlockList;
  287. end;
  288. end;
  289. procedure TThreadList.UnlockList;
  290. begin
  291. end;
  292. {
  293. $Log$
  294. Revision 1.4 2000-11-17 13:39:49 sg
  295. * Extended Error methods so that exceptions are raised from the caller's
  296. address instead of the Error method
  297. Revision 1.3 2000/09/14 18:39:31 michael
  298. + Fixed setcapacity
  299. Revision 1.2 2000/07/13 11:32:59 michael
  300. + removed logs
  301. }