lists.inc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1998 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. Runerror (255);
  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. Runerror(255);
  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. RunError (255);
  44. If NewCapacity>FCapacity then
  45. begin
  46. GetMem (NewList,NewCapacity*SizeOf(Pointer));
  47. If NewList=Nil then
  48. Runerror(255);
  49. If Assigned(FList) then
  50. begin
  51. System.Move (FList^,NewList^,FCapacity*Sizeof(Pointer));
  52. FillWord (NewList^[FCapacity],(NewCapacity-FCapacity)*WordRatio, 0);
  53. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  54. end;
  55. Flist:=NewList;
  56. FCapacity:=NewCapacity;
  57. end
  58. else if NewCapacity<FCapacity then
  59. begin
  60. If NewCapacity<0 then
  61. RunError(255);
  62. ToFree:=Flist+NewCapacity*SizeOf(Pointer);
  63. FreeMem (ToFree, (FCapacity-NewCapacity)*SizeOf(Pointer));
  64. FCapacity:=NewCapacity;
  65. end;
  66. end;
  67. procedure TList.SetCount(NewCount: Integer);
  68. begin
  69. If (NewCount<0) or (NewCount>MaxListSize)then
  70. RunError(255);
  71. If NewCount<FCount then
  72. FCount:=NewCount
  73. else If NewCount>FCount then
  74. begin
  75. If NewCount>FCapacity then
  76. SetCapacity (NewCount);
  77. If FCount<NewCount then
  78. FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
  79. FCount:=Newcount;
  80. end;
  81. end;
  82. destructor TList.Destroy;
  83. begin
  84. Self.Clear;
  85. inherited Destroy;
  86. end;
  87. Function TList.Add(Item: Pointer): Integer;
  88. begin
  89. Self.Insert (Count,Item);
  90. Result:=Count-1;
  91. end;
  92. Procedure TList.Clear;
  93. begin
  94. If Assigned(FList) then
  95. begin
  96. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  97. FList:=Nil;
  98. FCapacity:=0;
  99. FCount:=0;
  100. end;
  101. end;
  102. Procedure TList.Delete(Index: Integer);
  103. begin
  104. If (Index<0) or (Index>=FCount) then
  105. Runerror(255);
  106. FCount:=FCount-1;
  107. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  108. end;
  109. class procedure TList.Error(const Msg: string; Data: Integer);
  110. begin
  111. Writeln (Msg);
  112. RunError(255);
  113. end;
  114. procedure TList.Exchange(Index1, Index2: Integer);
  115. var Temp : Pointer;
  116. begin
  117. If ((Index1>=FCount) or (Index2>=FCount)) or
  118. ((Index1<0) or (Index2<0)) then
  119. RunError(255);
  120. Temp:=FList^[Index1];
  121. FList^[Index1]:=FList^[Index2];
  122. FList^[Index2]:=Temp;
  123. end;
  124. function TList.Expand: TList;
  125. Var IncSize : Longint;
  126. begin
  127. if FCount<FCapacity then exit;
  128. IncSize:=4;
  129. if FCapacity>3 then IncSize:=IncSize+4;
  130. if FCapacity>8 then IncSize:=IncSize+8;
  131. SetCapacity(FCapacity+IncSize);
  132. Result:=Self;
  133. end;
  134. function TList.First: Pointer;
  135. begin
  136. // Wouldn't it be better to return Nil if count is zero ?
  137. Result:=Items[0];
  138. end;
  139. function TList.IndexOf(Item: Pointer): Integer;
  140. begin
  141. Result:=0;
  142. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  143. If Result=FCount then Result:=-1;
  144. end;
  145. procedure TList.Insert(Index: Integer; Item: Pointer);
  146. begin
  147. If (Index<0) or (Index>FCount )then
  148. RunError(255);
  149. IF FCount=FCapacity Then Self.Expand;
  150. If Index<FCount then
  151. System.Move (Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  152. FList^[Index]:=Item;
  153. FCount:=FCount+1;
  154. end;
  155. function TList.Last: Pointer;
  156. Var I : longint;
  157. begin
  158. // Wouldn't it be better to return nil if the count is zero ?
  159. Result:=Items[FCount-1];
  160. end;
  161. procedure TList.Move(CurIndex, NewIndex: Integer);
  162. Var Temp : Pointer;
  163. begin
  164. If ((CurIndex<0) or (CurIndex>Count-1)) or (NewINdex<0) then
  165. RunError(255);
  166. Temp:=FList^[CurIndex];
  167. Self.Delete(CurIndex);
  168. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  169. // Newindex changes when deleting ??
  170. Self.Insert (NewIndex,Temp);
  171. end;
  172. function TList.Remove(Item: Pointer): Integer;
  173. begin
  174. Result:=IndexOf(Item);
  175. If Result<>-1 then
  176. Self.Delete (Result);
  177. end;
  178. Procedure TList.Pack;
  179. Var {Last,I,J,}Runner : Longint;
  180. begin
  181. // Not the fastest; but surely correct
  182. For Runner:=Fcount-1 downto 0 do
  183. if Items[Runner]=Nil then Self.Delete(Runner);
  184. { The following may be faster in case of large and defragmented lists
  185. If count=0 then exit;
  186. Runner:=0;I:=0;
  187. TheLast:=Count;
  188. while runner<count do
  189. begin
  190. // Find first Nil
  191. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  192. if Runner<Count do
  193. begin
  194. // Start searching for non-nil from last known nil+1
  195. if i<Runner then I:=Runner+1;
  196. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  197. // Start looking for last non-nil of block.
  198. J:=I+1;
  199. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  200. // Move block and zero out
  201. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  202. FillWord (Flist^[I],(J-I)*WordRatio,0);
  203. // Update Runner and Last to point behind last block
  204. TheLast:=Runner+(J-I);
  205. If J=Count then
  206. begin
  207. // Shortcut, when J=Count we checked all pointers
  208. Runner:=Count
  209. else
  210. begin
  211. Runner:=TheLast;
  212. I:=j;
  213. end;
  214. end;
  215. Count:=TheLast;
  216. }
  217. end;
  218. // Needed by Sort method.
  219. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  220. Compare : TListSortCompare);
  221. Var I,J : Longint;
  222. P,Q : Pointer;
  223. begin
  224. Repeat
  225. I:=L;
  226. J:=R;
  227. P:=FList^[ (L+R) div 2 ];
  228. repeat
  229. While Compare(P,FList^[i])>0 Do I:=I+1;
  230. While Compare(P,FList^[J])<0 Do J:=J-1;
  231. If I<=J then
  232. begin
  233. Q:=Flist^[I];
  234. Flist^[I]:=FList^[J];
  235. FList^[J]:=Q;
  236. I:=I+1;
  237. J:=j-1;
  238. end;
  239. Until I>J;
  240. If L<J then QuickSort (FList,L,J,Compare);
  241. L:=I;
  242. Until I>=R;
  243. end;
  244. procedure TList.Sort(Compare: TListSortCompare);
  245. begin
  246. If Not Assigned(FList) or (FCount<2) then exit;
  247. QuickSort (Flist, 0, FCount-1,Compare);
  248. end;
  249. {****************************************************************************}
  250. {* TThreadList *}
  251. {****************************************************************************}
  252. constructor TThreadList.Create;
  253. begin
  254. end;
  255. destructor TThreadList.Destroy;
  256. begin
  257. end;
  258. procedure TThreadList.Add(Item: Pointer);
  259. begin
  260. end;
  261. procedure TThreadList.Clear;
  262. begin
  263. end;
  264. function TThreadList.LockList: TList;
  265. begin
  266. end;
  267. procedure TThreadList.Remove(Item: Pointer);
  268. begin
  269. end;
  270. procedure TThreadList.UnlockList;
  271. begin
  272. end;
  273. {
  274. $Log$
  275. Revision 1.4 1998-05-06 07:27:22 michael
  276. + Fixec index check in exchange method.
  277. Revision 1.3 1998/05/05 15:54:31 michael
  278. TList completely implemented
  279. Revision 1.2 1998/05/04 15:54:07 michael
  280. + Partial implementation of TList
  281. Revision 1.1 1998/05/04 14:30:12 michael
  282. * Split file according to Class; implemented dummys for all methods, so unit compiles.
  283. }