fgl.pp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  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. Result := InternalItems[Index];
  446. if Index<FCount then
  447. begin
  448. System.Move(Result^, (Result+FItemSize)^, (FCount - Index) * FItemSize);
  449. { clear for compiler assisted types }
  450. System.FillByte(Result^, FItemSize, 0);
  451. end;
  452. Inc(FCount);
  453. end;
  454. procedure TFPSList.Insert(Index: Integer; Item: Pointer);
  455. begin
  456. CopyItem(Item, Insert(Index));
  457. end;
  458. function TFPSList.Last: Pointer;
  459. begin
  460. if FCount = 0 then
  461. Result := nil
  462. else
  463. Result := InternalItems[FCount - 1];
  464. end;
  465. procedure TFPSList.Move(CurIndex, NewIndex: Integer);
  466. var
  467. CurItem, NewItem, TmpItem, Src, Dest: Pointer;
  468. MoveCount: Integer;
  469. begin
  470. if (CurIndex < 0) or (CurIndex >= Count) then
  471. Error(SListIndexError, CurIndex);
  472. if (NewIndex < 0) or (NewIndex >= Count) then
  473. Error(SListIndexError, NewIndex);
  474. if CurIndex = NewIndex then
  475. exit;
  476. CurItem := InternalItems[CurIndex];
  477. NewItem := InternalItems[NewIndex];
  478. TmpItem := InternalItems[FCapacity];
  479. System.Move(CurItem^, TmpItem^, FItemSize);
  480. if NewIndex > CurIndex then
  481. begin
  482. Src := InternalItems[CurIndex+1];
  483. Dest := CurItem;
  484. MoveCount := NewIndex - CurIndex;
  485. end else begin
  486. Src := NewItem;
  487. Dest := InternalItems[NewIndex+1];
  488. MoveCount := CurIndex - NewIndex;
  489. end;
  490. System.Move(Src^, Dest^, MoveCount * FItemSize);
  491. System.Move(TmpItem^, NewItem^, FItemSize);
  492. end;
  493. function TFPSList.Remove(Item: Pointer): Integer;
  494. begin
  495. Result := IndexOf(Item);
  496. if Result <> -1 then
  497. Delete(Result);
  498. end;
  499. procedure TFPSList.Pack;
  500. var
  501. NewCount,
  502. i : integer;
  503. pdest,
  504. psrc : Pointer;
  505. begin
  506. NewCount:=0;
  507. psrc:=First;
  508. pdest:=psrc;
  509. For I:=0 To FCount-1 Do
  510. begin
  511. if assigned(pointer(psrc^)) then
  512. begin
  513. System.Move(psrc^, pdest^, FItemSize);
  514. inc(pdest);
  515. inc(NewCount);
  516. end;
  517. inc(psrc);
  518. end;
  519. FCount:=NewCount;
  520. end;
  521. // Needed by Sort method.
  522. procedure TFPSList.QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
  523. var
  524. I, J, P: Integer;
  525. PivotItem: Pointer;
  526. begin
  527. repeat
  528. I := L;
  529. J := R;
  530. P := (L + R) div 2;
  531. repeat
  532. PivotItem := InternalItems[P];
  533. while Compare(PivotItem, InternalItems[I]) > 0 do
  534. Inc(I);
  535. while Compare(PivotItem, InternalItems[J]) < 0 do
  536. Dec(J);
  537. if I <= J then
  538. begin
  539. InternalExchange(I, J);
  540. if P = I then
  541. P := J
  542. else if P = J then
  543. P := I;
  544. Inc(I);
  545. Dec(J);
  546. end;
  547. until I > J;
  548. if L < J then
  549. QuickSort(L, J, Compare);
  550. L := I;
  551. until I >= R;
  552. end;
  553. procedure TFPSList.Sort(Compare: TFPSListCompareFunc);
  554. begin
  555. if not Assigned(FList) or (FCount < 2) then exit;
  556. QuickSort(0, FCount-1, Compare);
  557. end;
  558. procedure TFPSList.Assign(Obj: TFPSList);
  559. var
  560. i: Integer;
  561. begin
  562. if Obj.ItemSize <> FItemSize then
  563. Error(SListItemSizeError, 0);
  564. Clear;
  565. for I := 0 to Obj.Count - 1 do
  566. Add(Obj[i]);
  567. end;
  568. {$ifndef VER2_0}
  569. {****************************************************************************}
  570. {* TFPGListEnumerator *}
  571. {****************************************************************************}
  572. function TFPGListEnumerator.GetCurrent: T;
  573. begin
  574. Result := T(FList.Items[FPosition]^);
  575. end;
  576. constructor TFPGListEnumerator.Create(AList: TFPSList);
  577. begin
  578. inherited Create;
  579. FList := AList;
  580. FPosition := -1;
  581. end;
  582. function TFPGListEnumerator.MoveNext: Boolean;
  583. begin
  584. inc(FPosition);
  585. Result := FPosition < FList.Count;
  586. end;
  587. {****************************************************************************}
  588. {* TFPGList *}
  589. {****************************************************************************}
  590. constructor TFPGList.Create;
  591. begin
  592. inherited Create(sizeof(T));
  593. end;
  594. procedure TFPGList.CopyItem(Src, Dest: Pointer);
  595. begin
  596. T(Dest^) := T(Src^);
  597. end;
  598. procedure TFPGList.Deref(Item: Pointer);
  599. begin
  600. Finalize(T(Item^));
  601. end;
  602. function TFPGList.Get(Index: Integer): T;
  603. begin
  604. Result := T(inherited Get(Index)^);
  605. end;
  606. function TFPGList.GetList: PTypeList;
  607. begin
  608. Result := PTypeList(FList);
  609. end;
  610. function TFPGList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  611. begin
  612. Result := FOnCompare(T(Item1^), T(Item2^));
  613. end;
  614. procedure TFPGList.Put(Index: Integer; const Item: T);
  615. begin
  616. inherited Put(Index, @Item);
  617. end;
  618. function TFPGList.Add(const Item: T): Integer;
  619. begin
  620. Result := inherited Add(@Item);
  621. end;
  622. function TFPGList.Extract(const Item: T): T;
  623. var
  624. ResPtr: Pointer;
  625. begin
  626. ResPtr := inherited Extract(@Item);
  627. if ResPtr <> nil then
  628. Result := T(ResPtr^)
  629. else
  630. FillByte(Result, sizeof(T), 0);
  631. end;
  632. function TFPGList.First: T;
  633. begin
  634. Result := T(inherited First^);
  635. end;
  636. function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
  637. begin
  638. Result := TFPGListEnumeratorSpec.Create(Self);
  639. end;
  640. function TFPGList.IndexOf(const Item: T): Integer;
  641. begin
  642. Result := 0;
  643. {$info TODO: fix inlining to work! InternalItems[Result]^}
  644. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  645. Inc(Result);
  646. if Result = FCount then
  647. Result := -1;
  648. end;
  649. procedure TFPGList.Insert(Index: Integer; const Item: T);
  650. begin
  651. T(inherited Insert(Index)^) := Item;
  652. end;
  653. function TFPGList.Last: T;
  654. begin
  655. Result := T(inherited Last^);
  656. end;
  657. function TFPGList.Remove(const Item: T): Integer;
  658. begin
  659. Result := IndexOf(Item);
  660. if Result >= 0 then
  661. Delete(Result);
  662. end;
  663. procedure TFPGList.Sort(Compare: TCompareFunc);
  664. begin
  665. FOnCompare := Compare;
  666. inherited Sort(@ItemPtrCompare);
  667. end;
  668. {****************************************************************************}
  669. {* TFPGObjectList *}
  670. {****************************************************************************}
  671. constructor TFPGObjectList.Create(FreeObjects: Boolean);
  672. begin
  673. inherited Create;
  674. FFreeObjects := FreeObjects;
  675. end;
  676. procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
  677. begin
  678. T(Dest^) := T(Src^);
  679. {if TObject(Dest^) is TInterfacedObject then
  680. T(Dest^)._AddRef;}
  681. end;
  682. procedure TFPGObjectList.Deref(Item: Pointer);
  683. begin
  684. {if TObject(Item^) is TInterfacedObject then
  685. T(Item^)._Release
  686. else}
  687. if FFreeObjects then
  688. T(Item^).Free;
  689. end;
  690. function TFPGObjectList.Get(Index: Integer): T;
  691. begin
  692. Result := T(inherited Get(Index)^);
  693. end;
  694. function TFPGObjectList.GetList: PTypeList;
  695. begin
  696. Result := PTypeList(FList);
  697. end;
  698. function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  699. begin
  700. Result := FOnCompare(T(Item1^), T(Item2^));
  701. end;
  702. procedure TFPGObjectList.Put(Index: Integer; const Item: T);
  703. begin
  704. inherited Put(Index, @Item);
  705. end;
  706. function TFPGObjectList.Add(const Item: T): Integer;
  707. begin
  708. Result := inherited Add(@Item);
  709. end;
  710. function TFPGObjectList.Extract(const Item: T): T;
  711. var
  712. ResPtr: Pointer;
  713. begin
  714. ResPtr := inherited Extract(@Item);
  715. if ResPtr <> nil then
  716. Result := T(ResPtr^)
  717. else
  718. FillByte(Result, sizeof(T), 0);
  719. end;
  720. function TFPGObjectList.First: T;
  721. begin
  722. Result := T(inherited First^);
  723. end;
  724. function TFPGObjectList.IndexOf(const Item: T): Integer;
  725. begin
  726. Result := 0;
  727. {$info TODO: fix inlining to work! InternalItems[Result]^}
  728. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  729. Inc(Result);
  730. if Result = FCount then
  731. Result := -1;
  732. end;
  733. procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
  734. begin
  735. T(inherited Insert(Index)^) := Item;
  736. end;
  737. function TFPGObjectList.Last: T;
  738. begin
  739. Result := T(inherited Last^);
  740. end;
  741. function TFPGObjectList.Remove(const Item: T): Integer;
  742. begin
  743. Result := IndexOf(Item);
  744. if Result >= 0 then
  745. Delete(Result);
  746. end;
  747. procedure TFPGObjectList.Sort(Compare: TCompareFunc);
  748. begin
  749. FOnCompare := Compare;
  750. inherited Sort(@ItemPtrCompare);
  751. end;
  752. {****************************************************************************}
  753. {* TFPGInterfacedObjectList *}
  754. {****************************************************************************}
  755. constructor TFPGInterfacedObjectList.Create;
  756. begin
  757. inherited Create;
  758. end;
  759. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  760. begin
  761. T(Dest^) := T(Src^);
  762. if Assigned(Pointer(Dest^)) then
  763. T(Dest^)._AddRef;
  764. end;
  765. procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
  766. begin
  767. if Assigned(Pointer(Item^)) then
  768. T(Item^)._Release;
  769. end;
  770. function TFPGInterfacedObjectList.Get(Index: Integer): T;
  771. begin
  772. Result := T(inherited Get(Index)^);
  773. end;
  774. function TFPGInterfacedObjectList.GetList: PTypeList;
  775. begin
  776. Result := PTypeList(FList);
  777. end;
  778. function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  779. begin
  780. Result := FOnCompare(T(Item1^), T(Item2^));
  781. end;
  782. procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
  783. begin
  784. inherited Put(Index, @Item);
  785. end;
  786. function TFPGInterfacedObjectList.Add(const Item: T): Integer;
  787. begin
  788. Result := inherited Add(@Item);
  789. end;
  790. function TFPGInterfacedObjectList.Extract(const Item: T): T;
  791. var
  792. ResPtr: Pointer;
  793. begin
  794. ResPtr := inherited Extract(@Item);
  795. if ResPtr <> nil then
  796. Result := T(ResPtr^)
  797. else
  798. FillByte(Result, sizeof(T), 0);
  799. end;
  800. function TFPGInterfacedObjectList.First: T;
  801. begin
  802. Result := T(inherited First^);
  803. end;
  804. function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
  805. begin
  806. Result := 0;
  807. {$info TODO: fix inlining to work! InternalItems[Result]^}
  808. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  809. Inc(Result);
  810. if Result = FCount then
  811. Result := -1;
  812. end;
  813. procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
  814. begin
  815. T(inherited Insert(Index)^) := Item;
  816. end;
  817. function TFPGInterfacedObjectList.Last: T;
  818. begin
  819. Result := T(inherited Last^);
  820. end;
  821. function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
  822. begin
  823. Result := IndexOf(Item);
  824. if Result >= 0 then
  825. Delete(Result);
  826. end;
  827. procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
  828. begin
  829. FOnCompare := Compare;
  830. inherited Sort(@ItemPtrCompare);
  831. end;
  832. {$endif}
  833. {****************************************************************************
  834. TFPSMap
  835. ****************************************************************************}
  836. constructor TFPSMap.Create(AKeySize: Integer; ADataSize: integer);
  837. begin
  838. inherited Create(AKeySize+ADataSize);
  839. FKeySize := AKeySize;
  840. FDataSize := ADataSize;
  841. InitOnPtrCompare;
  842. end;
  843. procedure TFPSMap.CopyKey(Src, Dest: Pointer);
  844. begin
  845. System.Move(Src^, Dest^, FKeySize);
  846. end;
  847. procedure TFPSMap.CopyData(Src, Dest: Pointer);
  848. begin
  849. System.Move(Src^, Dest^, FDataSize);
  850. end;
  851. function TFPSMap.BinaryCompare(Key1, Key2: Pointer): Integer;
  852. begin
  853. Result := CompareByte(Key1^, Key2^, FKeySize);
  854. end;
  855. function TFPSMap.GetKey(Index: Integer): Pointer;
  856. begin
  857. Result := Items[Index];
  858. end;
  859. function TFPSMap.GetData(Index: Integer): Pointer;
  860. begin
  861. Result := PByte(Items[Index])+FKeySize;
  862. end;
  863. function TFPSMap.GetKeyData(AKey: Pointer): Pointer;
  864. var
  865. I: Integer;
  866. begin
  867. I := IndexOf(AKey);
  868. if I >= 0 then
  869. Result := InternalItems[I]+FKeySize
  870. else
  871. Error(SMapKeyError, PtrUInt(AKey));
  872. end;
  873. procedure TFPSMap.InitOnPtrCompare;
  874. begin
  875. FOnPtrCompare := @BinaryCompare;
  876. end;
  877. procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
  878. begin
  879. if FSorted then
  880. Error(SSortedListError, 0);
  881. CopyKey(AKey, Items[Index]);
  882. end;
  883. procedure TFPSMap.PutData(Index: Integer; AData: Pointer);
  884. begin
  885. CopyData(AData, PByte(Items[Index])+FKeySize);
  886. end;
  887. procedure TFPSMap.PutKeyData(AKey: Pointer; NewData: Pointer);
  888. var
  889. I: Integer;
  890. begin
  891. I := IndexOf(AKey);
  892. if I >= 0 then
  893. Data[I] := NewData
  894. else
  895. Add(AKey, NewData);
  896. end;
  897. procedure TFPSMap.SetSorted(Value: Boolean);
  898. begin
  899. if Value = FSorted then exit;
  900. FSorted := Value;
  901. if Value then Sort;
  902. end;
  903. function TFPSMap.Add(AKey: Pointer): Integer;
  904. begin
  905. if Sorted then
  906. begin
  907. if Find(AKey, Result) then
  908. case Duplicates of
  909. dupIgnore: exit;
  910. dupError: Error(SDuplicateItem, 0)
  911. end;
  912. end else
  913. Result := Count;
  914. CopyKey(AKey, inherited Insert(Result));
  915. end;
  916. function TFPSMap.Add(AKey, AData: Pointer): Integer;
  917. begin
  918. Result := Add(AKey);
  919. Data[Result] := AData;
  920. end;
  921. function TFPSMap.Find(AKey: Pointer; var Index: Integer): Boolean;
  922. { Searches for the first item <= Key, returns True if exact match,
  923. sets index to the index f the found string. }
  924. var
  925. I,L,R,Dir: Integer;
  926. begin
  927. Result := false;
  928. // Use binary search.
  929. L := 0;
  930. R := FCount-1;
  931. while L<=R do
  932. begin
  933. I := (L+R) div 2;
  934. Dir := FOnPtrCompare(Items[I], AKey);
  935. if Dir < 0 then
  936. L := I+1
  937. else begin
  938. R := I-1;
  939. if Dir = 0 then
  940. begin
  941. Result := true;
  942. if Duplicates <> dupAccept then
  943. L := I;
  944. end;
  945. end;
  946. end;
  947. Index := L;
  948. end;
  949. function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
  950. var
  951. ListItem: Pointer;
  952. begin
  953. Result := 0;
  954. ListItem := First;
  955. while (Result < FCount) and (FOnPtrCompare(ListItem, AKey) <> 0) do
  956. begin
  957. Inc(Result);
  958. ListItem := PByte(ListItem)+FItemSize;
  959. end;
  960. if Result = FCount then Result := -1;
  961. end;
  962. function TFPSMap.IndexOf(AKey: Pointer): Integer;
  963. begin
  964. if Sorted then
  965. begin
  966. if not Find(AKey, Result) then
  967. Result := -1;
  968. end else
  969. Result := LinearIndexOf(AKey);
  970. end;
  971. function TFPSMap.IndexOfData(AData: Pointer): Integer;
  972. var
  973. ListItem: Pointer;
  974. begin
  975. Result := 0;
  976. ListItem := First+FKeySize;
  977. while (Result < FCount) and (CompareByte(ListItem^, AData^, FDataSize) <> 0) do
  978. begin
  979. Inc(Result);
  980. ListItem := PByte(ListItem)+FItemSize;
  981. end;
  982. if Result = FCount then Result := -1;
  983. end;
  984. function TFPSMap.Insert(Index: Integer): Pointer;
  985. begin
  986. if FSorted then
  987. Error(SSortedListError, 0);
  988. Result := inherited Insert(Index);
  989. end;
  990. procedure TFPSMap.Insert(Index: Integer; var AKey, AData: Pointer);
  991. begin
  992. AKey := Insert(Index);
  993. AData := PByte(AKey) + FKeySize;
  994. end;
  995. procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
  996. begin
  997. CopyKey(AKey, Insert(Index));
  998. end;
  999. procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
  1000. var
  1001. ListItem: Pointer;
  1002. begin
  1003. ListItem := Insert(Index);
  1004. CopyKey(AKey, ListItem);
  1005. CopyData(AData, PByte(ListItem)+FKeySize);
  1006. end;
  1007. function TFPSMap.Remove(AKey: Pointer): Integer;
  1008. begin
  1009. Result := IndexOf(AKey);
  1010. if Result >= 0 then
  1011. Delete(Result);
  1012. end;
  1013. procedure TFPSMap.Sort;
  1014. begin
  1015. inherited Sort(FOnPtrCompare);
  1016. end;
  1017. {****************************************************************************
  1018. TFPGMap
  1019. ****************************************************************************}
  1020. {$ifndef VER2_0}
  1021. constructor TFPGMap.Create;
  1022. begin
  1023. inherited Create(SizeOf(TKey), SizeOf(TData));
  1024. end;
  1025. procedure TFPGMap.CopyItem(Src, Dest: Pointer);
  1026. begin
  1027. CopyKey(Src, Dest);
  1028. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1029. end;
  1030. procedure TFPGMap.CopyKey(Src, Dest: Pointer);
  1031. begin
  1032. TKey(Dest^) := TKey(Src^);
  1033. end;
  1034. procedure TFPGMap.CopyData(Src, Dest: Pointer);
  1035. begin
  1036. TData(Dest^) := TData(Src^);
  1037. end;
  1038. procedure TFPGMap.Deref(Item: Pointer);
  1039. begin
  1040. Finalize(TKey(Item^));
  1041. Finalize(TData(Pointer(PByte(Item)+KeySize)^));
  1042. end;
  1043. function TFPGMap.GetKey(Index: Integer): TKey;
  1044. begin
  1045. Result := TKey(inherited GetKey(Index)^);
  1046. end;
  1047. function TFPGMap.GetData(Index: Integer): TData;
  1048. begin
  1049. Result := TData(inherited GetData(Index)^);
  1050. end;
  1051. function TFPGMap.GetKeyData(const AKey: TKey): TData;
  1052. begin
  1053. Result := TData(inherited GetKeyData(@AKey)^);
  1054. end;
  1055. procedure TFPGMap.InitOnPtrCompare;
  1056. begin
  1057. OnPtrCompare := @KeyCompare;
  1058. end;
  1059. function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
  1060. begin
  1061. if PKey(Key1)^ < PKey(Key2)^ then
  1062. Result := -1
  1063. else if PKey(Key1)^ > PKey(Key2)^ then
  1064. Result := 1
  1065. else
  1066. Result := 0;
  1067. end;
  1068. function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1069. begin
  1070. Result := FOnCompare(TKey(Key1^), TKey(Key2^));
  1071. end;
  1072. procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
  1073. begin
  1074. inherited PutKey(Index, @NewKey);
  1075. end;
  1076. procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
  1077. begin
  1078. inherited PutData(Index, @NewData);
  1079. end;
  1080. procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
  1081. begin
  1082. inherited PutKeyData(@AKey, @NewData);
  1083. end;
  1084. procedure TFPGMap.SetOnCompare(NewCompare: TCompareFunc);
  1085. begin
  1086. FOnCompare := NewCompare;
  1087. if NewCompare <> nil then
  1088. OnPtrCompare := @KeyCustomCompare
  1089. else
  1090. InitOnPtrCompare;
  1091. end;
  1092. function TFPGMap.Add(const AKey: TKey): Integer;
  1093. begin
  1094. Result := inherited Add(@AKey);
  1095. end;
  1096. function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
  1097. begin
  1098. Result := inherited Add(@AKey, @AData);
  1099. end;
  1100. function TFPGMap.Find(const AKey: TKey; var Index: Integer): Boolean;
  1101. begin
  1102. Result := inherited Find(@AKey, Index);
  1103. end;
  1104. function TFPGMap.IndexOf(const AKey: TKey): Integer;
  1105. begin
  1106. Result := inherited IndexOf(@AKey);
  1107. end;
  1108. function TFPGMap.IndexOfData(const AData: TData): Integer;
  1109. begin
  1110. { TODO: loop ? }
  1111. Result := inherited IndexOfData(@AData);
  1112. end;
  1113. procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
  1114. begin
  1115. inherited InsertKey(Index, @AKey);
  1116. end;
  1117. procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1118. begin
  1119. inherited InsertKeyData(Index, @AKey, @AData);
  1120. end;
  1121. function TFPGMap.Remove(const AKey: TKey): Integer;
  1122. begin
  1123. Result := inherited Remove(@AKey);
  1124. end;
  1125. {$endif}
  1126. end.