fgl.pp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2006 by Micha Nelissen
  4. member of the Free Pascal development team
  5. It contains the Free Pascal generics library
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$mode objfpc}
  13. { be aware, this unit is a prototype and subject to be changed heavily }
  14. unit fgl;
  15. interface
  16. uses
  17. types, sysutils;
  18. const
  19. MaxListSize = Maxint div 16;
  20. type
  21. EListError = class(Exception);
  22. TFPSList = class;
  23. TFPSListCompareFunc = function(Key1, Key2: Pointer): Integer of object;
  24. TFPSList = class(TObject)
  25. protected
  26. FList: PByte;
  27. FCount: Integer;
  28. FCapacity: Integer; { list is one longer than capacity, for temp }
  29. FItemSize: Integer;
  30. procedure CopyItem(Src, Dest: Pointer); virtual;
  31. procedure Deref(Item: Pointer); virtual; overload;
  32. procedure Deref(FromIndex, ToIndex: Integer); overload;
  33. function Get(Index: Integer): Pointer;
  34. procedure InternalExchange(Index1, Index2: Integer);
  35. function InternalGet(Index: Integer): Pointer; {$ifdef CLASSESINLINE} inline; {$endif}
  36. procedure InternalPut(Index: Integer; NewItem: Pointer);
  37. procedure Put(Index: Integer; Item: Pointer);
  38. procedure QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
  39. procedure SetCapacity(NewCapacity: Integer);
  40. procedure SetCount(NewCount: Integer);
  41. procedure RaiseIndexError(Index : Integer);
  42. property InternalItems[Index: Integer]: Pointer read InternalGet write InternalPut;
  43. public
  44. constructor Create(AItemSize: Integer = sizeof(Pointer));
  45. destructor Destroy; override;
  46. function Add(Item: Pointer): Integer;
  47. procedure Clear;
  48. procedure Delete(Index: Integer);
  49. class procedure Error(const Msg: string; Data: PtrInt);
  50. procedure Exchange(Index1, Index2: Integer);
  51. function Expand: TFPSList;
  52. function Extract(Item: Pointer): Pointer;
  53. function First: Pointer;
  54. function IndexOf(Item: Pointer): Integer;
  55. procedure Insert(Index: Integer; Item: Pointer);
  56. function Insert(Index: Integer): Pointer;
  57. function Last: Pointer;
  58. procedure Move(CurIndex, NewIndex: Integer);
  59. procedure Assign(Obj: TFPSList);
  60. function Remove(Item: Pointer): Integer;
  61. procedure Pack;
  62. procedure Sort(Compare: TFPSListCompareFunc);
  63. property Capacity: Integer read FCapacity write SetCapacity;
  64. property Count: Integer read FCount write SetCount;
  65. property Items[Index: Integer]: Pointer read Get write Put; default;
  66. property ItemSize: Integer read FItemSize;
  67. property List: PByte read FList;
  68. end;
  69. {$ifndef VER2_0}
  70. const
  71. MaxGListSize = MaxInt div 1024;
  72. type
  73. generic TFPGListEnumerator<T> = class(TObject)
  74. var protected
  75. FList: TFPSList;
  76. FPosition: Integer;
  77. function GetCurrent: T;
  78. public
  79. constructor Create(AList: TFPSList);
  80. function MoveNext: Boolean;
  81. property Current: T read GetCurrent;
  82. end;
  83. generic TFPGList<T> = class(TFPSList)
  84. type public
  85. TCompareFunc = function(const Item1, Item2: T): Integer;
  86. TTypeList = array[0..MaxGListSize] of T;
  87. PTypeList = ^TTypeList;
  88. PT = ^T;
  89. TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
  90. var protected
  91. FOnCompare: TCompareFunc;
  92. procedure CopyItem(Src, Dest: Pointer); override;
  93. procedure Deref(Item: Pointer); override;
  94. function Get(Index: Integer): T; {$ifdef CLASSESINLINE} inline; {$endif}
  95. function GetList: PTypeList; {$ifdef CLASSESINLINE} inline; {$endif}
  96. function ItemPtrCompare(Item1, Item2: Pointer): Integer;
  97. procedure Put(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
  98. public
  99. constructor Create;
  100. function Add(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  101. function Extract(const Item: T): T; {$ifdef CLASSESINLINE} inline; {$endif}
  102. function First: T; {$ifdef CLASSESINLINE} inline; {$endif}
  103. function GetEnumerator: TFPGListEnumeratorSpec; {$ifdef CLASSESINLINE} inline; {$endif}
  104. function IndexOf(const Item: T): Integer;
  105. procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
  106. function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
  107. {$info FIXME: bug #10479: implement TFPGList<T>.Assign(TFPGList) to work somehow}
  108. {procedure Assign(Source: TFPGList);}
  109. function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  110. procedure Sort(Compare: TCompareFunc);
  111. property Items[Index: Integer]: T read Get write Put; default;
  112. property List: PTypeList read GetList;
  113. end;
  114. generic TFPGObjectList<T> = class(TFPSList)
  115. type public
  116. TCompareFunc = function(const Item1, Item2: T): Integer;
  117. TTypeList = array[0..MaxGListSize] of T;
  118. PTypeList = ^TTypeList;
  119. PT = ^T;
  120. var protected
  121. FOnCompare: TCompareFunc;
  122. FFreeObjects: Boolean;
  123. procedure CopyItem(Src, Dest: Pointer); override;
  124. procedure Deref(Item: Pointer); override;
  125. function Get(Index: Integer): T; {$ifdef CLASSESINLINE} inline; {$endif}
  126. function GetList: PTypeList; {$ifdef CLASSESINLINE} inline; {$endif}
  127. function ItemPtrCompare(Item1, Item2: Pointer): Integer;
  128. procedure Put(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
  129. public
  130. constructor Create(FreeObjects: Boolean = True);
  131. function Add(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  132. function Extract(const Item: T): T; {$ifdef CLASSESINLINE} inline; {$endif}
  133. function First: T; {$ifdef CLASSESINLINE} inline; {$endif}
  134. function IndexOf(const Item: T): Integer;
  135. procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
  136. function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
  137. {$info FIXME: bug #10479: implement TFPGObjectList<T>.Assign(TFPGList) to work somehow}
  138. {procedure Assign(Source: TFPGList);}
  139. function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  140. procedure Sort(Compare: TCompareFunc);
  141. property Items[Index: Integer]: T read Get write Put; default;
  142. property List: PTypeList read GetList;
  143. property FreeObjects: Boolean read FFreeObjects write FFreeObjects;
  144. end;
  145. generic TFPGInterfacedObjectList<T> = class(TFPSList)
  146. type public
  147. TCompareFunc = function(const Item1, Item2: T): Integer;
  148. TTypeList = array[0..MaxGListSize] of T;
  149. PTypeList = ^TTypeList;
  150. PT = ^T;
  151. var protected
  152. FOnCompare: TCompareFunc;
  153. procedure CopyItem(Src, Dest: Pointer); override;
  154. procedure Deref(Item: Pointer); override;
  155. function Get(Index: Integer): T; {$ifdef CLASSESINLINE} inline; {$endif}
  156. function GetList: PTypeList; {$ifdef CLASSESINLINE} inline; {$endif}
  157. function ItemPtrCompare(Item1, Item2: Pointer): Integer;
  158. procedure Put(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
  159. public
  160. constructor Create;
  161. function Add(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  162. function Extract(const Item: T): T; {$ifdef CLASSESINLINE} inline; {$endif}
  163. function First: T; {$ifdef CLASSESINLINE} inline; {$endif}
  164. function IndexOf(const Item: T): Integer;
  165. procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
  166. function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
  167. {$info FIXME: bug #10479: implement TFPGInterfacedObjectList<T>.Assign(TFPGList) to work somehow}
  168. {procedure Assign(Source: TFPGList);}
  169. function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  170. procedure Sort(Compare: TCompareFunc);
  171. property Items[Index: Integer]: T read Get write Put; default;
  172. property List: PTypeList read GetList;
  173. end;
  174. {$endif}
  175. TFPSMap = class(TFPSList)
  176. private
  177. FKeySize: Integer;
  178. FDataSize: Integer;
  179. FDuplicates: TDuplicates;
  180. FSorted: Boolean;
  181. FOnPtrCompare: TFPSListCompareFunc;
  182. procedure SetSorted(Value: Boolean);
  183. protected
  184. function BinaryCompare(Key1, Key2: Pointer): Integer;
  185. procedure CopyKey(Src, Dest: Pointer); virtual;
  186. procedure CopyData(Src, Dest: Pointer); virtual;
  187. function GetKey(Index: Integer): Pointer;
  188. function GetKeyData(AKey: Pointer): Pointer;
  189. function GetData(Index: Integer): Pointer;
  190. procedure InitOnPtrCompare; virtual;
  191. function LinearIndexOf(AKey: Pointer): Integer;
  192. procedure PutKey(Index: Integer; AKey: Pointer);
  193. procedure PutKeyData(AKey: Pointer; NewData: Pointer);
  194. procedure PutData(Index: Integer; AData: Pointer);
  195. public
  196. constructor Create(AKeySize: Integer = sizeof(Pointer);
  197. ADataSize: integer = sizeof(Pointer));
  198. function Add(AKey, AData: Pointer): Integer;
  199. function Add(AKey: Pointer): Integer;
  200. function Find(AKey: Pointer; var Index: Integer): Boolean;
  201. function IndexOf(AKey: Pointer): Integer;
  202. function IndexOfData(AData: Pointer): Integer;
  203. function Insert(Index: Integer): Pointer;
  204. procedure Insert(Index: Integer; var AKey, AData: Pointer);
  205. procedure InsertKey(Index: Integer; AKey: Pointer);
  206. procedure InsertKeyData(Index: Integer; AKey, AData: Pointer);
  207. function Remove(AKey: Pointer): Integer;
  208. procedure Sort;
  209. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  210. property KeySize: Integer read FKeySize;
  211. property DataSize: Integer read FDataSize;
  212. property Keys[Index: Integer]: Pointer read GetKey write PutKey;
  213. property Data[Index: Integer]: Pointer read GetData write PutData;
  214. property KeyData[Key: Pointer]: Pointer read GetKeyData write PutKeyData; default;
  215. property Sorted: Boolean read FSorted write SetSorted;
  216. property OnPtrCompare: TFPSListCompareFunc read FOnPtrCompare write FOnPtrCompare;
  217. end;
  218. {$ifndef VER2_0}
  219. generic TFPGMap<TKey, TData> = class(TFPSMap)
  220. type public
  221. TCompareFunc = function(const Key1, Key2: TKey): Integer;
  222. PKey = ^TKey;
  223. PData = ^TData;
  224. var protected
  225. FOnCompare: TCompareFunc;
  226. procedure CopyItem(Src, Dest: Pointer); override;
  227. procedure CopyKey(Src, Dest: Pointer); override;
  228. procedure CopyData(Src, Dest: Pointer); override;
  229. procedure Deref(Item: Pointer); override;
  230. procedure InitOnPtrCompare; override;
  231. function GetKey(Index: Integer): TKey; {$ifdef CLASSESINLINE} inline; {$endif}
  232. function GetKeyData(const AKey: TKey): TData; {$ifdef CLASSESINLINE} inline; {$endif}
  233. function GetData(Index: Integer): TData; {$ifdef CLASSESINLINE} inline; {$endif}
  234. function KeyCompare(Key1, Key2: Pointer): Integer;
  235. function KeyCustomCompare(Key1, Key2: Pointer): Integer;
  236. procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef CLASSESINLINE} inline; {$endif}
  237. procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
  238. procedure PutData(Index: Integer; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
  239. procedure SetOnCompare(NewCompare: TCompareFunc);
  240. public
  241. constructor Create;
  242. function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  243. function Add(const AKey: TKey): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  244. function Find(const AKey: TKey; var Index: Integer): Boolean; {$ifdef CLASSESINLINE} inline; {$endif}
  245. function IndexOf(const AKey: TKey): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  246. function IndexOfData(const AData: TData): Integer;
  247. procedure InsertKey(Index: Integer; const AKey: TKey);
  248. procedure InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  249. function Remove(const AKey: TKey): Integer;
  250. property Keys[Index: Integer]: TKey read GetKey write PutKey;
  251. property Data[Index: Integer]: TData read GetData write PutData;
  252. property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
  253. property OnCompare: TCompareFunc read FOnCompare write SetOnCompare;
  254. end;
  255. {$endif}
  256. implementation
  257. uses
  258. rtlconsts;
  259. {****************************************************************************
  260. TFPSList
  261. ****************************************************************************}
  262. constructor TFPSList.Create(AItemSize: integer);
  263. begin
  264. inherited Create;
  265. FItemSize := AItemSize;
  266. end;
  267. destructor TFPSList.Destroy;
  268. begin
  269. Clear;
  270. // Clear() does not clear the whole list; there is always a single temp entry
  271. // at the end which is never freed. Take care of that one here.
  272. FreeMem(FList);
  273. inherited Destroy;
  274. end;
  275. procedure TFPSList.CopyItem(Src, Dest: Pointer);
  276. begin
  277. System.Move(Src^, Dest^, FItemSize);
  278. end;
  279. procedure TFPSList.RaiseIndexError(Index : Integer);
  280. begin
  281. Error(SListIndexError, Index);
  282. end;
  283. function TFPSList.InternalGet(Index: Integer): Pointer;
  284. begin
  285. Result:=FList+Index*ItemSize;
  286. end;
  287. procedure TFPSList.InternalPut(Index: Integer; NewItem: Pointer);
  288. var
  289. ListItem: Pointer;
  290. begin
  291. ListItem := InternalItems[Index];
  292. CopyItem(NewItem, ListItem);
  293. end;
  294. function TFPSList.Get(Index: Integer): Pointer;
  295. begin
  296. if (Index < 0) or (Index >= FCount) then
  297. RaiseIndexError(Index);
  298. Result := InternalItems[Index];
  299. end;
  300. procedure TFPSList.Put(Index: Integer; Item: Pointer);
  301. begin
  302. if (Index < 0) or (Index >= FCount) then
  303. RaiseIndexError(Index);
  304. InternalItems[Index] := Item;
  305. end;
  306. procedure TFPSList.SetCapacity(NewCapacity: Integer);
  307. begin
  308. if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
  309. Error(SListCapacityError, NewCapacity);
  310. if NewCapacity = FCapacity then
  311. exit;
  312. ReallocMem(FList, (NewCapacity+1) * FItemSize);
  313. FillChar(InternalItems[FCapacity]^, (NewCapacity+1-FCapacity) * FItemSize, #0);
  314. FCapacity := NewCapacity;
  315. end;
  316. procedure TFPSList.Deref(Item: Pointer);
  317. begin
  318. end;
  319. procedure TFPSList.Deref(FromIndex, ToIndex: Integer);
  320. var
  321. ListItem, ListItemLast: Pointer;
  322. begin
  323. ListItem := InternalItems[FromIndex];
  324. ListItemLast := InternalItems[ToIndex];
  325. repeat
  326. Deref(ListItem);
  327. if ListItem = ListItemLast then
  328. break;
  329. ListItem := PByte(ListItem) + ItemSize;
  330. until false;
  331. end;
  332. procedure TFPSList.SetCount(NewCount: Integer);
  333. begin
  334. if (NewCount < 0) or (NewCount > MaxListSize) then
  335. Error(SListCountError, NewCount);
  336. if NewCount > FCapacity then
  337. SetCapacity(NewCount);
  338. if NewCount > FCount then
  339. FillByte(InternalItems[FCount]^, (NewCount-FCount) * FItemSize, 0)
  340. else if NewCount < FCount then
  341. Deref(NewCount, FCount-1);
  342. FCount := NewCount;
  343. end;
  344. function TFPSList.Add(Item: Pointer): Integer;
  345. begin
  346. if FCount = FCapacity then
  347. Self.Expand;
  348. CopyItem(Item, InternalItems[FCount]);
  349. Result := FCount;
  350. Inc(FCount);
  351. end;
  352. procedure TFPSList.Clear;
  353. begin
  354. if Assigned(FList) then
  355. begin
  356. SetCount(0);
  357. SetCapacity(0);
  358. end;
  359. end;
  360. procedure TFPSList.Delete(Index: Integer);
  361. var
  362. ListItem: Pointer;
  363. begin
  364. if (Index < 0) or (Index >= FCount) then
  365. Error(SListIndexError, Index);
  366. Dec(FCount);
  367. ListItem := InternalItems[Index];
  368. Deref(ListItem);
  369. System.Move(InternalItems[Index+1]^, ListItem^, (FCount - Index) * FItemSize);
  370. // Shrink the list if appropriate
  371. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  372. begin
  373. FCapacity := FCapacity shr 1;
  374. ReallocMem(FList, (FCapacity+1) * FItemSize);
  375. end;
  376. end;
  377. function TFPSList.Extract(Item: Pointer): Pointer;
  378. var
  379. i : Integer;
  380. begin
  381. Result := nil;
  382. i := IndexOf(Item);
  383. if i >= 0 then
  384. begin
  385. Result := InternalItems[i];
  386. System.Move(Result^, InternalItems[FCapacity]^, FItemSize);
  387. Delete(i);
  388. end;
  389. end;
  390. class procedure TFPSList.Error(const Msg: string; Data: PtrInt);
  391. begin
  392. raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  393. end;
  394. procedure TFPSList.Exchange(Index1, Index2: Integer);
  395. begin
  396. if ((Index1 >= FCount) or (Index1 < 0)) then
  397. Error(SListIndexError, Index1);
  398. if ((Index2 >= FCount) or (Index2 < 0)) then
  399. Error(SListIndexError, Index2);
  400. InternalExchange(Index1, Index2);
  401. end;
  402. procedure TFPSList.InternalExchange(Index1, Index2: Integer);
  403. begin
  404. System.Move(InternalItems[Index1]^, InternalItems[FCapacity]^, FItemSize);
  405. System.Move(InternalItems[Index2]^, InternalItems[Index1]^, FItemSize);
  406. System.Move(InternalItems[FCapacity]^, InternalItems[Index2]^, FItemSize);
  407. end;
  408. function TFPSList.Expand: TFPSList;
  409. var
  410. IncSize : Longint;
  411. begin
  412. if FCount < FCapacity then exit;
  413. IncSize := 4;
  414. if FCapacity > 3 then IncSize := IncSize + 4;
  415. if FCapacity > 8 then IncSize := IncSize + 8;
  416. if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
  417. SetCapacity(FCapacity + IncSize);
  418. Result := Self;
  419. end;
  420. function TFPSList.First: Pointer;
  421. begin
  422. If FCount = 0 then
  423. Result := Nil
  424. else
  425. Result := InternalItems[0];
  426. end;
  427. function TFPSList.IndexOf(Item: Pointer): Integer;
  428. var
  429. ListItem: Pointer;
  430. begin
  431. Result := 0;
  432. ListItem := First;
  433. while (Result < FCount) and (CompareByte(ListItem^, Item^, FItemSize) <> 0) do
  434. begin
  435. Inc(Result);
  436. ListItem := PByte(ListItem)+FItemSize;
  437. end;
  438. if Result = FCount then Result := -1;
  439. end;
  440. function TFPSList.Insert(Index: Integer): Pointer;
  441. begin
  442. if (Index < 0) or (Index > FCount) then
  443. Error(SListIndexError, Index);
  444. if FCount = FCapacity then Self.Expand;
  445. if Index<FCount then
  446. System.Move(InternalItems[Index]^, InternalItems[Index+1]^, (FCount - Index) * FItemSize);
  447. Result := InternalItems[Index];
  448. Inc(FCount);
  449. end;
  450. procedure TFPSList.Insert(Index: Integer; Item: Pointer);
  451. begin
  452. CopyItem(Item, Insert(Index));
  453. end;
  454. function TFPSList.Last: Pointer;
  455. begin
  456. if FCount = 0 then
  457. Result := nil
  458. else
  459. Result := InternalItems[FCount - 1];
  460. end;
  461. procedure TFPSList.Move(CurIndex, NewIndex: Integer);
  462. var
  463. CurItem, NewItem, TmpItem, Src, Dest: Pointer;
  464. MoveCount: Integer;
  465. begin
  466. if (CurIndex < 0) or (CurIndex >= Count) then
  467. Error(SListIndexError, CurIndex);
  468. if (NewIndex < 0) or (NewIndex >= Count) then
  469. Error(SListIndexError, NewIndex);
  470. if CurIndex = NewIndex then
  471. exit;
  472. CurItem := InternalItems[CurIndex];
  473. NewItem := InternalItems[NewIndex];
  474. TmpItem := InternalItems[FCapacity];
  475. System.Move(CurItem^, TmpItem^, FItemSize);
  476. if NewIndex > CurIndex then
  477. begin
  478. Src := InternalItems[CurIndex+1];
  479. Dest := CurItem;
  480. MoveCount := NewIndex - CurIndex;
  481. end else begin
  482. Src := NewItem;
  483. Dest := InternalItems[NewIndex+1];
  484. MoveCount := CurIndex - NewIndex;
  485. end;
  486. System.Move(Src^, Dest^, MoveCount * FItemSize);
  487. System.Move(TmpItem^, NewItem^, FItemSize);
  488. end;
  489. function TFPSList.Remove(Item: Pointer): Integer;
  490. begin
  491. Result := IndexOf(Item);
  492. if Result <> -1 then
  493. Delete(Result);
  494. end;
  495. procedure TFPSList.Pack;
  496. var
  497. NewCount,
  498. i : integer;
  499. pdest,
  500. psrc : Pointer;
  501. begin
  502. NewCount:=0;
  503. psrc:=First;
  504. pdest:=psrc;
  505. For I:=0 To FCount-1 Do
  506. begin
  507. if assigned(pointer(psrc^)) then
  508. begin
  509. System.Move(psrc^, pdest^, FItemSize);
  510. inc(pdest);
  511. inc(NewCount);
  512. end;
  513. inc(psrc);
  514. end;
  515. FCount:=NewCount;
  516. end;
  517. // Needed by Sort method.
  518. procedure TFPSList.QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
  519. var
  520. I, J, P: Integer;
  521. PivotItem: Pointer;
  522. begin
  523. repeat
  524. I := L;
  525. J := R;
  526. P := (L + R) div 2;
  527. repeat
  528. PivotItem := InternalItems[P];
  529. while Compare(PivotItem, InternalItems[I]) > 0 do
  530. Inc(I);
  531. while Compare(PivotItem, InternalItems[J]) < 0 do
  532. Dec(J);
  533. if I <= J then
  534. begin
  535. InternalExchange(I, J);
  536. if P = I then
  537. P := J
  538. else if P = J then
  539. P := I;
  540. Inc(I);
  541. Dec(J);
  542. end;
  543. until I > J;
  544. if L < J then
  545. QuickSort(L, J, Compare);
  546. L := I;
  547. until I >= R;
  548. end;
  549. procedure TFPSList.Sort(Compare: TFPSListCompareFunc);
  550. begin
  551. if not Assigned(FList) or (FCount < 2) then exit;
  552. QuickSort(0, FCount-1, Compare);
  553. end;
  554. procedure TFPSList.Assign(Obj: TFPSList);
  555. var
  556. i: Integer;
  557. begin
  558. if Obj.ItemSize <> FItemSize then
  559. Error(SListItemSizeError, 0);
  560. Clear;
  561. for I := 0 to Obj.Count - 1 do
  562. Add(Obj[i]);
  563. end;
  564. {$ifndef VER2_0}
  565. {****************************************************************************}
  566. {* TFPGListEnumerator *}
  567. {****************************************************************************}
  568. function TFPGListEnumerator.GetCurrent: T;
  569. begin
  570. Result := T(FList.Items[FPosition]^);
  571. end;
  572. constructor TFPGListEnumerator.Create(AList: TFPSList);
  573. begin
  574. inherited Create;
  575. FList := AList;
  576. FPosition := -1;
  577. end;
  578. function TFPGListEnumerator.MoveNext: Boolean;
  579. begin
  580. inc(FPosition);
  581. Result := FPosition < FList.Count;
  582. end;
  583. {****************************************************************************}
  584. {* TFPGList *}
  585. {****************************************************************************}
  586. constructor TFPGList.Create;
  587. begin
  588. inherited Create(sizeof(T));
  589. end;
  590. procedure TFPGList.CopyItem(Src, Dest: Pointer);
  591. begin
  592. T(Dest^) := T(Src^);
  593. end;
  594. procedure TFPGList.Deref(Item: Pointer);
  595. begin
  596. Finalize(T(Item^));
  597. end;
  598. function TFPGList.Get(Index: Integer): T;
  599. begin
  600. Result := T(inherited Get(Index)^);
  601. end;
  602. function TFPGList.GetList: PTypeList;
  603. begin
  604. Result := PTypeList(FList);
  605. end;
  606. function TFPGList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  607. begin
  608. Result := FOnCompare(T(Item1^), T(Item2^));
  609. end;
  610. procedure TFPGList.Put(Index: Integer; const Item: T);
  611. begin
  612. inherited Put(Index, @Item);
  613. end;
  614. function TFPGList.Add(const Item: T): Integer;
  615. begin
  616. Result := inherited Add(@Item);
  617. end;
  618. function TFPGList.Extract(const Item: T): T;
  619. var
  620. ResPtr: Pointer;
  621. begin
  622. ResPtr := inherited Extract(@Item);
  623. if ResPtr <> nil then
  624. Result := T(ResPtr^)
  625. else
  626. FillByte(Result, 0, sizeof(T));
  627. end;
  628. function TFPGList.First: T;
  629. begin
  630. Result := T(inherited First^);
  631. end;
  632. function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
  633. begin
  634. Result := TFPGListEnumeratorSpec.Create(Self);
  635. end;
  636. function TFPGList.IndexOf(const Item: T): Integer;
  637. begin
  638. Result := 0;
  639. {$info TODO: fix inlining to work! InternalItems[Result]^}
  640. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  641. Inc(Result);
  642. if Result = FCount then
  643. Result := -1;
  644. end;
  645. procedure TFPGList.Insert(Index: Integer; const Item: T);
  646. begin
  647. T(inherited Insert(Index)^) := Item;
  648. end;
  649. function TFPGList.Last: T;
  650. begin
  651. Result := T(inherited Last^);
  652. end;
  653. function TFPGList.Remove(const Item: T): Integer;
  654. begin
  655. Result := IndexOf(Item);
  656. if Result >= 0 then
  657. Delete(Result);
  658. end;
  659. procedure TFPGList.Sort(Compare: TCompareFunc);
  660. begin
  661. FOnCompare := Compare;
  662. inherited Sort(@ItemPtrCompare);
  663. end;
  664. {****************************************************************************}
  665. {* TFPGObjectList *}
  666. {****************************************************************************}
  667. constructor TFPGObjectList.Create(FreeObjects: Boolean);
  668. begin
  669. inherited Create;
  670. FFreeObjects := FreeObjects;
  671. end;
  672. procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
  673. begin
  674. T(Dest^) := T(Src^);
  675. {if TObject(Dest^) is TInterfacedObject then
  676. T(Dest^)._AddRef;}
  677. end;
  678. procedure TFPGObjectList.Deref(Item: Pointer);
  679. begin
  680. {if TObject(Item^) is TInterfacedObject then
  681. T(Item^)._Release
  682. else}
  683. if FFreeObjects then
  684. T(Item^).Free;
  685. end;
  686. function TFPGObjectList.Get(Index: Integer): T;
  687. begin
  688. Result := T(inherited Get(Index)^);
  689. end;
  690. function TFPGObjectList.GetList: PTypeList;
  691. begin
  692. Result := PTypeList(FList);
  693. end;
  694. function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  695. begin
  696. Result := FOnCompare(T(Item1^), T(Item2^));
  697. end;
  698. procedure TFPGObjectList.Put(Index: Integer; const Item: T);
  699. begin
  700. inherited Put(Index, @Item);
  701. end;
  702. function TFPGObjectList.Add(const Item: T): Integer;
  703. begin
  704. Result := inherited Add(@Item);
  705. end;
  706. function TFPGObjectList.Extract(const Item: T): T;
  707. var
  708. ResPtr: Pointer;
  709. begin
  710. ResPtr := inherited Extract(@Item);
  711. if ResPtr <> nil then
  712. Result := T(ResPtr^)
  713. else
  714. FillByte(Result, 0, sizeof(T));
  715. end;
  716. function TFPGObjectList.First: T;
  717. begin
  718. Result := T(inherited First^);
  719. end;
  720. function TFPGObjectList.IndexOf(const Item: T): Integer;
  721. begin
  722. Result := 0;
  723. {$info TODO: fix inlining to work! InternalItems[Result]^}
  724. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  725. Inc(Result);
  726. if Result = FCount then
  727. Result := -1;
  728. end;
  729. procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
  730. begin
  731. T(inherited Insert(Index)^) := Item;
  732. end;
  733. function TFPGObjectList.Last: T;
  734. begin
  735. Result := T(inherited Last^);
  736. end;
  737. function TFPGObjectList.Remove(const Item: T): Integer;
  738. begin
  739. Result := IndexOf(Item);
  740. if Result >= 0 then
  741. Delete(Result);
  742. end;
  743. procedure TFPGObjectList.Sort(Compare: TCompareFunc);
  744. begin
  745. FOnCompare := Compare;
  746. inherited Sort(@ItemPtrCompare);
  747. end;
  748. {****************************************************************************}
  749. {* TFPGInterfacedObjectList *}
  750. {****************************************************************************}
  751. constructor TFPGInterfacedObjectList.Create;
  752. begin
  753. inherited Create;
  754. end;
  755. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  756. begin
  757. T(Dest^) := T(Src^);
  758. if Assigned(Pointer(Dest^)) then
  759. T(Dest^)._AddRef;
  760. end;
  761. procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
  762. begin
  763. if Assigned(Pointer(Item^)) then
  764. T(Item^)._Release;
  765. end;
  766. function TFPGInterfacedObjectList.Get(Index: Integer): T;
  767. begin
  768. Result := T(inherited Get(Index)^);
  769. end;
  770. function TFPGInterfacedObjectList.GetList: PTypeList;
  771. begin
  772. Result := PTypeList(FList);
  773. end;
  774. function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  775. begin
  776. Result := FOnCompare(T(Item1^), T(Item2^));
  777. end;
  778. procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
  779. begin
  780. inherited Put(Index, @Item);
  781. end;
  782. function TFPGInterfacedObjectList.Add(const Item: T): Integer;
  783. begin
  784. Result := inherited Add(@Item);
  785. end;
  786. function TFPGInterfacedObjectList.Extract(const Item: T): T;
  787. var
  788. ResPtr: Pointer;
  789. begin
  790. ResPtr := inherited Extract(@Item);
  791. if ResPtr <> nil then
  792. Result := T(ResPtr^)
  793. else
  794. FillByte(Result, 0, sizeof(T));
  795. end;
  796. function TFPGInterfacedObjectList.First: T;
  797. begin
  798. Result := T(inherited First^);
  799. end;
  800. function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
  801. begin
  802. Result := 0;
  803. {$info TODO: fix inlining to work! InternalItems[Result]^}
  804. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  805. Inc(Result);
  806. if Result = FCount then
  807. Result := -1;
  808. end;
  809. procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
  810. begin
  811. T(inherited Insert(Index)^) := Item;
  812. end;
  813. function TFPGInterfacedObjectList.Last: T;
  814. begin
  815. Result := T(inherited Last^);
  816. end;
  817. function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
  818. begin
  819. Result := IndexOf(Item);
  820. if Result >= 0 then
  821. Delete(Result);
  822. end;
  823. procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
  824. begin
  825. FOnCompare := Compare;
  826. inherited Sort(@ItemPtrCompare);
  827. end;
  828. {$endif}
  829. {****************************************************************************
  830. TFPSMap
  831. ****************************************************************************}
  832. constructor TFPSMap.Create(AKeySize: Integer; ADataSize: integer);
  833. begin
  834. inherited Create(AKeySize+ADataSize);
  835. FKeySize := AKeySize;
  836. FDataSize := ADataSize;
  837. InitOnPtrCompare;
  838. end;
  839. procedure TFPSMap.CopyKey(Src, Dest: Pointer);
  840. begin
  841. System.Move(Src^, Dest^, FKeySize);
  842. end;
  843. procedure TFPSMap.CopyData(Src, Dest: Pointer);
  844. begin
  845. System.Move(Src^, Dest^, FDataSize);
  846. end;
  847. function TFPSMap.BinaryCompare(Key1, Key2: Pointer): Integer;
  848. begin
  849. Result := CompareByte(Key1^, Key2^, FKeySize);
  850. end;
  851. function TFPSMap.GetKey(Index: Integer): Pointer;
  852. begin
  853. Result := Items[Index];
  854. end;
  855. function TFPSMap.GetData(Index: Integer): Pointer;
  856. begin
  857. Result := PByte(Items[Index])+FKeySize;
  858. end;
  859. function TFPSMap.GetKeyData(AKey: Pointer): Pointer;
  860. var
  861. I: Integer;
  862. begin
  863. I := IndexOf(AKey);
  864. if I >= 0 then
  865. Result := InternalItems[I]+FKeySize
  866. else
  867. Error(SMapKeyError, PtrUInt(AKey));
  868. end;
  869. procedure TFPSMap.InitOnPtrCompare;
  870. begin
  871. FOnPtrCompare := @BinaryCompare;
  872. end;
  873. procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
  874. begin
  875. if FSorted then
  876. Error(SSortedListError, 0);
  877. CopyKey(AKey, Items[Index]);
  878. end;
  879. procedure TFPSMap.PutData(Index: Integer; AData: Pointer);
  880. begin
  881. CopyData(AData, PByte(Items[Index])+FKeySize);
  882. end;
  883. procedure TFPSMap.PutKeyData(AKey: Pointer; NewData: Pointer);
  884. var
  885. I: Integer;
  886. begin
  887. I := IndexOf(AKey);
  888. if I >= 0 then
  889. Data[I] := NewData
  890. else
  891. Add(AKey, NewData);
  892. end;
  893. procedure TFPSMap.SetSorted(Value: Boolean);
  894. begin
  895. if Value = FSorted then exit;
  896. FSorted := Value;
  897. if Value then Sort;
  898. end;
  899. function TFPSMap.Add(AKey: Pointer): Integer;
  900. begin
  901. if Sorted then
  902. begin
  903. if Find(AKey, Result) then
  904. case Duplicates of
  905. dupIgnore: exit;
  906. dupError: Error(SDuplicateItem, 0)
  907. end;
  908. end else
  909. Result := Count;
  910. CopyKey(AKey, inherited Insert(Result));
  911. end;
  912. function TFPSMap.Add(AKey, AData: Pointer): Integer;
  913. begin
  914. Result := Add(AKey);
  915. Data[Result] := AData;
  916. end;
  917. function TFPSMap.Find(AKey: Pointer; var Index: Integer): Boolean;
  918. { Searches for the first item <= Key, returns True if exact match,
  919. sets index to the index f the found string. }
  920. var
  921. I,L,R,Dir: Integer;
  922. begin
  923. Result := false;
  924. // Use binary search.
  925. L := 0;
  926. R := FCount-1;
  927. while L<=R do
  928. begin
  929. I := (L+R) div 2;
  930. Dir := FOnPtrCompare(Items[I], AKey);
  931. if Dir < 0 then
  932. L := I+1
  933. else begin
  934. R := I-1;
  935. if Dir = 0 then
  936. begin
  937. Result := true;
  938. if Duplicates <> dupAccept then
  939. L := I;
  940. end;
  941. end;
  942. end;
  943. Index := L;
  944. end;
  945. function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
  946. var
  947. ListItem: Pointer;
  948. begin
  949. Result := 0;
  950. ListItem := First;
  951. while (Result < FCount) and (FOnPtrCompare(ListItem, AKey) <> 0) do
  952. begin
  953. Inc(Result);
  954. ListItem := PByte(ListItem)+FItemSize;
  955. end;
  956. if Result = FCount then Result := -1;
  957. end;
  958. function TFPSMap.IndexOf(AKey: Pointer): Integer;
  959. begin
  960. if Sorted then
  961. begin
  962. if not Find(AKey, Result) then
  963. Result := -1;
  964. end else
  965. Result := LinearIndexOf(AKey);
  966. end;
  967. function TFPSMap.IndexOfData(AData: Pointer): Integer;
  968. var
  969. ListItem: Pointer;
  970. begin
  971. Result := 0;
  972. ListItem := First+FKeySize;
  973. while (Result < FCount) and (CompareByte(ListItem^, AData^, FDataSize) <> 0) do
  974. begin
  975. Inc(Result);
  976. ListItem := PByte(ListItem)+FItemSize;
  977. end;
  978. if Result = FCount then Result := -1;
  979. end;
  980. function TFPSMap.Insert(Index: Integer): Pointer;
  981. begin
  982. if FSorted then
  983. Error(SSortedListError, 0);
  984. Result := inherited Insert(Index);
  985. end;
  986. procedure TFPSMap.Insert(Index: Integer; var AKey, AData: Pointer);
  987. begin
  988. AKey := Insert(Index);
  989. AData := PByte(AKey) + FKeySize;
  990. end;
  991. procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
  992. begin
  993. CopyKey(AKey, Insert(Index));
  994. end;
  995. procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
  996. var
  997. ListItem: Pointer;
  998. begin
  999. ListItem := Insert(Index);
  1000. CopyKey(AKey, ListItem);
  1001. CopyData(AData, PByte(ListItem)+FKeySize);
  1002. end;
  1003. function TFPSMap.Remove(AKey: Pointer): Integer;
  1004. begin
  1005. Result := IndexOf(AKey);
  1006. if Result >= 0 then
  1007. Delete(Result);
  1008. end;
  1009. procedure TFPSMap.Sort;
  1010. begin
  1011. inherited Sort(FOnPtrCompare);
  1012. end;
  1013. {****************************************************************************
  1014. TFPGMap
  1015. ****************************************************************************}
  1016. {$ifndef VER2_0}
  1017. constructor TFPGMap.Create;
  1018. begin
  1019. inherited Create(SizeOf(TKey), SizeOf(TData));
  1020. end;
  1021. procedure TFPGMap.CopyItem(Src, Dest: Pointer);
  1022. begin
  1023. CopyKey(Src, Dest);
  1024. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1025. end;
  1026. procedure TFPGMap.CopyKey(Src, Dest: Pointer);
  1027. begin
  1028. TKey(Dest^) := TKey(Src^);
  1029. end;
  1030. procedure TFPGMap.CopyData(Src, Dest: Pointer);
  1031. begin
  1032. TData(Dest^) := TData(Src^);
  1033. end;
  1034. procedure TFPGMap.Deref(Item: Pointer);
  1035. begin
  1036. Finalize(TKey(Item^));
  1037. Finalize(TData(Pointer(PByte(Item)+KeySize)^));
  1038. end;
  1039. function TFPGMap.GetKey(Index: Integer): TKey;
  1040. begin
  1041. Result := TKey(inherited GetKey(Index)^);
  1042. end;
  1043. function TFPGMap.GetData(Index: Integer): TData;
  1044. begin
  1045. Result := TData(inherited GetData(Index)^);
  1046. end;
  1047. function TFPGMap.GetKeyData(const AKey: TKey): TData;
  1048. begin
  1049. Result := TData(inherited GetKeyData(@AKey)^);
  1050. end;
  1051. procedure TFPGMap.InitOnPtrCompare;
  1052. begin
  1053. OnPtrCompare := @KeyCompare;
  1054. end;
  1055. function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
  1056. begin
  1057. if PKey(Key1)^ < PKey(Key2)^ then
  1058. Result := -1
  1059. else if PKey(Key1)^ > PKey(Key2)^ then
  1060. Result := 1
  1061. else
  1062. Result := 0;
  1063. end;
  1064. function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1065. begin
  1066. Result := FOnCompare(TKey(Key1^), TKey(Key2^));
  1067. end;
  1068. procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
  1069. begin
  1070. inherited PutKey(Index, @NewKey);
  1071. end;
  1072. procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
  1073. begin
  1074. inherited PutData(Index, @NewData);
  1075. end;
  1076. procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
  1077. begin
  1078. inherited PutKeyData(@AKey, @NewData);
  1079. end;
  1080. procedure TFPGMap.SetOnCompare(NewCompare: TCompareFunc);
  1081. begin
  1082. FOnCompare := NewCompare;
  1083. if NewCompare <> nil then
  1084. OnPtrCompare := @KeyCustomCompare
  1085. else
  1086. InitOnPtrCompare;
  1087. end;
  1088. function TFPGMap.Add(const AKey: TKey): Integer;
  1089. begin
  1090. Result := inherited Add(@AKey);
  1091. end;
  1092. function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
  1093. begin
  1094. Result := inherited Add(@AKey, @AData);
  1095. end;
  1096. function TFPGMap.Find(const AKey: TKey; var Index: Integer): Boolean;
  1097. begin
  1098. Result := inherited Find(@AKey, Index);
  1099. end;
  1100. function TFPGMap.IndexOf(const AKey: TKey): Integer;
  1101. begin
  1102. Result := inherited IndexOf(@AKey);
  1103. end;
  1104. function TFPGMap.IndexOfData(const AData: TData): Integer;
  1105. begin
  1106. { TODO: loop ? }
  1107. Result := inherited IndexOfData(@AData);
  1108. end;
  1109. procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
  1110. begin
  1111. inherited InsertKey(Index, @AKey);
  1112. end;
  1113. procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1114. begin
  1115. inherited InsertKeyData(Index, @AKey, @AData);
  1116. end;
  1117. function TFPGMap.Remove(const AKey: TKey): Integer;
  1118. begin
  1119. Result := inherited Remove(@AKey);
  1120. end;
  1121. {$endif}
  1122. end.