fgl.pp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  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. FOnKeyPtrCompare: TFPSListCompareFunc;
  182. FOnDataPtrCompare: TFPSListCompareFunc;
  183. procedure SetSorted(Value: Boolean);
  184. protected
  185. function BinaryCompareKey(Key1, Key2: Pointer): Integer;
  186. function BinaryCompareData(Data1, Data2: Pointer): Integer;
  187. procedure SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
  188. procedure SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
  189. procedure InitOnPtrCompare; virtual;
  190. procedure CopyKey(Src, Dest: Pointer); virtual;
  191. procedure CopyData(Src, Dest: Pointer); virtual;
  192. function GetKey(Index: Integer): Pointer;
  193. function GetKeyData(AKey: Pointer): Pointer;
  194. function GetData(Index: Integer): Pointer;
  195. function LinearIndexOf(AKey: Pointer): Integer;
  196. procedure PutKey(Index: Integer; AKey: Pointer);
  197. procedure PutKeyData(AKey: Pointer; NewData: Pointer);
  198. procedure PutData(Index: Integer; AData: Pointer);
  199. public
  200. constructor Create(AKeySize: Integer = sizeof(Pointer);
  201. ADataSize: integer = sizeof(Pointer));
  202. function Add(AKey, AData: Pointer): Integer;
  203. function Add(AKey: Pointer): Integer;
  204. function Find(AKey: Pointer; out Index: Integer): Boolean;
  205. function IndexOf(AKey: Pointer): Integer;
  206. function IndexOfData(AData: Pointer): Integer;
  207. function Insert(Index: Integer): Pointer;
  208. procedure Insert(Index: Integer; out AKey, AData: Pointer);
  209. procedure InsertKey(Index: Integer; AKey: Pointer);
  210. procedure InsertKeyData(Index: Integer; AKey, AData: Pointer);
  211. function Remove(AKey: Pointer): Integer;
  212. procedure Sort;
  213. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  214. property KeySize: Integer read FKeySize;
  215. property DataSize: Integer read FDataSize;
  216. property Keys[Index: Integer]: Pointer read GetKey write PutKey;
  217. property Data[Index: Integer]: Pointer read GetData write PutData;
  218. property KeyData[Key: Pointer]: Pointer read GetKeyData write PutKeyData; default;
  219. property Sorted: Boolean read FSorted write SetSorted;
  220. property OnPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare; //deprecated;
  221. property OnKeyPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare;
  222. property OnDataPtrCompare: TFPSListCompareFunc read FOnDataPtrCompare write SetOnDataPtrCompare;
  223. end;
  224. {$ifndef VER2_0}
  225. generic TFPGMap<TKey, TData> = class(TFPSMap)
  226. type public
  227. TKeyCompareFunc = function(const Key1, Key2: TKey): Integer;
  228. TDataCompareFunc = function(const Data1, Data2: TData): Integer;
  229. PKey = ^TKey;
  230. PData = ^TData;
  231. var protected
  232. FOnKeyCompare: TKeyCompareFunc;
  233. FOnDataCompare: TDataCompareFunc;
  234. procedure CopyItem(Src, Dest: Pointer); override;
  235. procedure CopyKey(Src, Dest: Pointer); override;
  236. procedure CopyData(Src, Dest: Pointer); override;
  237. procedure Deref(Item: Pointer); override;
  238. procedure InitOnPtrCompare; override;
  239. function GetKey(Index: Integer): TKey; {$ifdef CLASSESINLINE} inline; {$endif}
  240. function GetKeyData(const AKey: TKey): TData; {$ifdef CLASSESINLINE} inline; {$endif}
  241. function GetData(Index: Integer): TData; {$ifdef CLASSESINLINE} inline; {$endif}
  242. function KeyCompare(Key1, Key2: Pointer): Integer;
  243. function KeyCustomCompare(Key1, Key2: Pointer): Integer;
  244. //function DataCompare(Data1, Data2: Pointer): Integer;
  245. function DataCustomCompare(Data1, Data2: Pointer): Integer;
  246. procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef CLASSESINLINE} inline; {$endif}
  247. procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
  248. procedure PutData(Index: Integer; const NewData: TData); {$ifdef CLASSESINLINE} inline; {$endif}
  249. procedure SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  250. procedure SetOnDataCompare(NewCompare: TDataCompareFunc);
  251. public
  252. constructor Create;
  253. function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  254. function Add(const AKey: TKey): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  255. function Find(const AKey: TKey; out Index: Integer): Boolean; {$ifdef CLASSESINLINE} inline; {$endif}
  256. function IndexOf(const AKey: TKey): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
  257. function IndexOfData(const AData: TData): Integer;
  258. procedure InsertKey(Index: Integer; const AKey: TKey);
  259. procedure InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  260. function Remove(const AKey: TKey): Integer;
  261. property Keys[Index: Integer]: TKey read GetKey write PutKey;
  262. property Data[Index: Integer]: TData read GetData write PutData;
  263. property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
  264. property OnCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare; //deprecated;
  265. property OnKeyCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare;
  266. property OnDataCompare: TDataCompareFunc read FOnDataCompare write SetOnDataCompare;
  267. end;
  268. {$endif}
  269. implementation
  270. uses
  271. rtlconsts;
  272. {****************************************************************************
  273. TFPSList
  274. ****************************************************************************}
  275. constructor TFPSList.Create(AItemSize: integer);
  276. begin
  277. inherited Create;
  278. FItemSize := AItemSize;
  279. end;
  280. destructor TFPSList.Destroy;
  281. begin
  282. Clear;
  283. // Clear() does not clear the whole list; there is always a single temp entry
  284. // at the end which is never freed. Take care of that one here.
  285. FreeMem(FList);
  286. inherited Destroy;
  287. end;
  288. procedure TFPSList.CopyItem(Src, Dest: Pointer);
  289. begin
  290. System.Move(Src^, Dest^, FItemSize);
  291. end;
  292. procedure TFPSList.RaiseIndexError(Index : Integer);
  293. begin
  294. Error(SListIndexError, Index);
  295. end;
  296. function TFPSList.InternalGet(Index: Integer): Pointer;
  297. begin
  298. Result:=FList+Index*ItemSize;
  299. end;
  300. procedure TFPSList.InternalPut(Index: Integer; NewItem: Pointer);
  301. var
  302. ListItem: Pointer;
  303. begin
  304. ListItem := InternalItems[Index];
  305. CopyItem(NewItem, ListItem);
  306. end;
  307. function TFPSList.Get(Index: Integer): Pointer;
  308. begin
  309. if (Index < 0) or (Index >= FCount) then
  310. RaiseIndexError(Index);
  311. Result := InternalItems[Index];
  312. end;
  313. procedure TFPSList.Put(Index: Integer; Item: Pointer);
  314. begin
  315. if (Index < 0) or (Index >= FCount) then
  316. RaiseIndexError(Index);
  317. InternalItems[Index] := Item;
  318. end;
  319. procedure TFPSList.SetCapacity(NewCapacity: Integer);
  320. begin
  321. if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
  322. Error(SListCapacityError, NewCapacity);
  323. if NewCapacity = FCapacity then
  324. exit;
  325. ReallocMem(FList, (NewCapacity+1) * FItemSize);
  326. FillChar(InternalItems[FCapacity]^, (NewCapacity+1-FCapacity) * FItemSize, #0);
  327. FCapacity := NewCapacity;
  328. end;
  329. procedure TFPSList.Deref(Item: Pointer);
  330. begin
  331. end;
  332. procedure TFPSList.Deref(FromIndex, ToIndex: Integer);
  333. var
  334. ListItem, ListItemLast: Pointer;
  335. begin
  336. ListItem := InternalItems[FromIndex];
  337. ListItemLast := InternalItems[ToIndex];
  338. repeat
  339. Deref(ListItem);
  340. if ListItem = ListItemLast then
  341. break;
  342. ListItem := PByte(ListItem) + ItemSize;
  343. until false;
  344. end;
  345. procedure TFPSList.SetCount(NewCount: Integer);
  346. begin
  347. if (NewCount < 0) or (NewCount > MaxListSize) then
  348. Error(SListCountError, NewCount);
  349. if NewCount > FCapacity then
  350. SetCapacity(NewCount);
  351. if NewCount > FCount then
  352. FillByte(InternalItems[FCount]^, (NewCount-FCount) * FItemSize, 0)
  353. else if NewCount < FCount then
  354. Deref(NewCount, FCount-1);
  355. FCount := NewCount;
  356. end;
  357. function TFPSList.Add(Item: Pointer): Integer;
  358. begin
  359. if FCount = FCapacity then
  360. Self.Expand;
  361. CopyItem(Item, InternalItems[FCount]);
  362. Result := FCount;
  363. Inc(FCount);
  364. end;
  365. procedure TFPSList.Clear;
  366. begin
  367. if Assigned(FList) then
  368. begin
  369. SetCount(0);
  370. SetCapacity(0);
  371. end;
  372. end;
  373. procedure TFPSList.Delete(Index: Integer);
  374. var
  375. ListItem: Pointer;
  376. begin
  377. if (Index < 0) or (Index >= FCount) then
  378. Error(SListIndexError, Index);
  379. Dec(FCount);
  380. ListItem := InternalItems[Index];
  381. Deref(ListItem);
  382. System.Move(InternalItems[Index+1]^, ListItem^, (FCount - Index) * FItemSize);
  383. // Shrink the list if appropriate
  384. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  385. begin
  386. FCapacity := FCapacity shr 1;
  387. ReallocMem(FList, (FCapacity+1) * FItemSize);
  388. end;
  389. end;
  390. function TFPSList.Extract(Item: Pointer): Pointer;
  391. var
  392. i : Integer;
  393. begin
  394. Result := nil;
  395. i := IndexOf(Item);
  396. if i >= 0 then
  397. begin
  398. Result := InternalItems[i];
  399. System.Move(Result^, InternalItems[FCapacity]^, FItemSize);
  400. Delete(i);
  401. end;
  402. end;
  403. class procedure TFPSList.Error(const Msg: string; Data: PtrInt);
  404. begin
  405. raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  406. end;
  407. procedure TFPSList.Exchange(Index1, Index2: Integer);
  408. begin
  409. if ((Index1 >= FCount) or (Index1 < 0)) then
  410. Error(SListIndexError, Index1);
  411. if ((Index2 >= FCount) or (Index2 < 0)) then
  412. Error(SListIndexError, Index2);
  413. InternalExchange(Index1, Index2);
  414. end;
  415. procedure TFPSList.InternalExchange(Index1, Index2: Integer);
  416. begin
  417. System.Move(InternalItems[Index1]^, InternalItems[FCapacity]^, FItemSize);
  418. System.Move(InternalItems[Index2]^, InternalItems[Index1]^, FItemSize);
  419. System.Move(InternalItems[FCapacity]^, InternalItems[Index2]^, FItemSize);
  420. end;
  421. function TFPSList.Expand: TFPSList;
  422. var
  423. IncSize : Longint;
  424. begin
  425. if FCount < FCapacity then exit;
  426. IncSize := 4;
  427. if FCapacity > 3 then IncSize := IncSize + 4;
  428. if FCapacity > 8 then IncSize := IncSize + 8;
  429. if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
  430. SetCapacity(FCapacity + IncSize);
  431. Result := Self;
  432. end;
  433. function TFPSList.First: Pointer;
  434. begin
  435. If FCount = 0 then
  436. Result := Nil
  437. else
  438. Result := InternalItems[0];
  439. end;
  440. function TFPSList.IndexOf(Item: Pointer): Integer;
  441. var
  442. ListItem: Pointer;
  443. begin
  444. Result := 0;
  445. ListItem := First;
  446. while (Result < FCount) and (CompareByte(ListItem^, Item^, FItemSize) <> 0) do
  447. begin
  448. Inc(Result);
  449. ListItem := PByte(ListItem)+FItemSize;
  450. end;
  451. if Result = FCount then Result := -1;
  452. end;
  453. function TFPSList.Insert(Index: Integer): Pointer;
  454. begin
  455. if (Index < 0) or (Index > FCount) then
  456. Error(SListIndexError, Index);
  457. if FCount = FCapacity then Self.Expand;
  458. Result := InternalItems[Index];
  459. if Index<FCount then
  460. begin
  461. System.Move(Result^, (Result+FItemSize)^, (FCount - Index) * FItemSize);
  462. { clear for compiler assisted types }
  463. System.FillByte(Result^, FItemSize, 0);
  464. end;
  465. Inc(FCount);
  466. end;
  467. procedure TFPSList.Insert(Index: Integer; Item: Pointer);
  468. begin
  469. CopyItem(Item, Insert(Index));
  470. end;
  471. function TFPSList.Last: Pointer;
  472. begin
  473. if FCount = 0 then
  474. Result := nil
  475. else
  476. Result := InternalItems[FCount - 1];
  477. end;
  478. procedure TFPSList.Move(CurIndex, NewIndex: Integer);
  479. var
  480. CurItem, NewItem, TmpItem, Src, Dest: Pointer;
  481. MoveCount: Integer;
  482. begin
  483. if (CurIndex < 0) or (CurIndex >= Count) then
  484. Error(SListIndexError, CurIndex);
  485. if (NewIndex < 0) or (NewIndex >= Count) then
  486. Error(SListIndexError, NewIndex);
  487. if CurIndex = NewIndex then
  488. exit;
  489. CurItem := InternalItems[CurIndex];
  490. NewItem := InternalItems[NewIndex];
  491. TmpItem := InternalItems[FCapacity];
  492. System.Move(CurItem^, TmpItem^, FItemSize);
  493. if NewIndex > CurIndex then
  494. begin
  495. Src := InternalItems[CurIndex+1];
  496. Dest := CurItem;
  497. MoveCount := NewIndex - CurIndex;
  498. end else begin
  499. Src := NewItem;
  500. Dest := InternalItems[NewIndex+1];
  501. MoveCount := CurIndex - NewIndex;
  502. end;
  503. System.Move(Src^, Dest^, MoveCount * FItemSize);
  504. System.Move(TmpItem^, NewItem^, FItemSize);
  505. end;
  506. function TFPSList.Remove(Item: Pointer): Integer;
  507. begin
  508. Result := IndexOf(Item);
  509. if Result <> -1 then
  510. Delete(Result);
  511. end;
  512. procedure TFPSList.Pack;
  513. var
  514. NewCount,
  515. i : integer;
  516. pdest,
  517. psrc : Pointer;
  518. begin
  519. NewCount:=0;
  520. psrc:=First;
  521. pdest:=psrc;
  522. For I:=0 To FCount-1 Do
  523. begin
  524. if assigned(pointer(psrc^)) then
  525. begin
  526. System.Move(psrc^, pdest^, FItemSize);
  527. inc(pdest);
  528. inc(NewCount);
  529. end;
  530. inc(psrc);
  531. end;
  532. FCount:=NewCount;
  533. end;
  534. // Needed by Sort method.
  535. procedure TFPSList.QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
  536. var
  537. I, J, P: Integer;
  538. PivotItem: Pointer;
  539. begin
  540. repeat
  541. I := L;
  542. J := R;
  543. P := (L + R) div 2;
  544. repeat
  545. PivotItem := InternalItems[P];
  546. while Compare(PivotItem, InternalItems[I]) > 0 do
  547. Inc(I);
  548. while Compare(PivotItem, InternalItems[J]) < 0 do
  549. Dec(J);
  550. if I <= J then
  551. begin
  552. InternalExchange(I, J);
  553. if P = I then
  554. P := J
  555. else if P = J then
  556. P := I;
  557. Inc(I);
  558. Dec(J);
  559. end;
  560. until I > J;
  561. if L < J then
  562. QuickSort(L, J, Compare);
  563. L := I;
  564. until I >= R;
  565. end;
  566. procedure TFPSList.Sort(Compare: TFPSListCompareFunc);
  567. begin
  568. if not Assigned(FList) or (FCount < 2) then exit;
  569. QuickSort(0, FCount-1, Compare);
  570. end;
  571. procedure TFPSList.Assign(Obj: TFPSList);
  572. var
  573. i: Integer;
  574. begin
  575. if Obj.ItemSize <> FItemSize then
  576. Error(SListItemSizeError, 0);
  577. Clear;
  578. for I := 0 to Obj.Count - 1 do
  579. Add(Obj[i]);
  580. end;
  581. {$ifndef VER2_0}
  582. {****************************************************************************}
  583. {* TFPGListEnumerator *}
  584. {****************************************************************************}
  585. function TFPGListEnumerator.GetCurrent: T;
  586. begin
  587. Result := T(FList.Items[FPosition]^);
  588. end;
  589. constructor TFPGListEnumerator.Create(AList: TFPSList);
  590. begin
  591. inherited Create;
  592. FList := AList;
  593. FPosition := -1;
  594. end;
  595. function TFPGListEnumerator.MoveNext: Boolean;
  596. begin
  597. inc(FPosition);
  598. Result := FPosition < FList.Count;
  599. end;
  600. {****************************************************************************}
  601. {* TFPGList *}
  602. {****************************************************************************}
  603. constructor TFPGList.Create;
  604. begin
  605. inherited Create(sizeof(T));
  606. end;
  607. procedure TFPGList.CopyItem(Src, Dest: Pointer);
  608. begin
  609. T(Dest^) := T(Src^);
  610. end;
  611. procedure TFPGList.Deref(Item: Pointer);
  612. begin
  613. Finalize(T(Item^));
  614. end;
  615. function TFPGList.Get(Index: Integer): T;
  616. begin
  617. Result := T(inherited Get(Index)^);
  618. end;
  619. function TFPGList.GetList: PTypeList;
  620. begin
  621. Result := PTypeList(FList);
  622. end;
  623. function TFPGList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  624. begin
  625. Result := FOnCompare(T(Item1^), T(Item2^));
  626. end;
  627. procedure TFPGList.Put(Index: Integer; const Item: T);
  628. begin
  629. inherited Put(Index, @Item);
  630. end;
  631. function TFPGList.Add(const Item: T): Integer;
  632. begin
  633. Result := inherited Add(@Item);
  634. end;
  635. function TFPGList.Extract(const Item: T): T;
  636. var
  637. ResPtr: Pointer;
  638. begin
  639. ResPtr := inherited Extract(@Item);
  640. if ResPtr <> nil then
  641. Result := T(ResPtr^)
  642. else
  643. FillByte(Result, sizeof(T), 0);
  644. end;
  645. function TFPGList.First: T;
  646. begin
  647. Result := T(inherited First^);
  648. end;
  649. function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
  650. begin
  651. Result := TFPGListEnumeratorSpec.Create(Self);
  652. end;
  653. function TFPGList.IndexOf(const Item: T): Integer;
  654. begin
  655. Result := 0;
  656. {$info TODO: fix inlining to work! InternalItems[Result]^}
  657. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  658. Inc(Result);
  659. if Result = FCount then
  660. Result := -1;
  661. end;
  662. procedure TFPGList.Insert(Index: Integer; const Item: T);
  663. begin
  664. T(inherited Insert(Index)^) := Item;
  665. end;
  666. function TFPGList.Last: T;
  667. begin
  668. Result := T(inherited Last^);
  669. end;
  670. function TFPGList.Remove(const Item: T): Integer;
  671. begin
  672. Result := IndexOf(Item);
  673. if Result >= 0 then
  674. Delete(Result);
  675. end;
  676. procedure TFPGList.Sort(Compare: TCompareFunc);
  677. begin
  678. FOnCompare := Compare;
  679. inherited Sort(@ItemPtrCompare);
  680. end;
  681. {****************************************************************************}
  682. {* TFPGObjectList *}
  683. {****************************************************************************}
  684. constructor TFPGObjectList.Create(FreeObjects: Boolean);
  685. begin
  686. inherited Create;
  687. FFreeObjects := FreeObjects;
  688. end;
  689. procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
  690. begin
  691. T(Dest^) := T(Src^);
  692. {if TObject(Dest^) is TInterfacedObject then
  693. T(Dest^)._AddRef;}
  694. end;
  695. procedure TFPGObjectList.Deref(Item: Pointer);
  696. begin
  697. {if TObject(Item^) is TInterfacedObject then
  698. T(Item^)._Release
  699. else}
  700. if FFreeObjects then
  701. T(Item^).Free;
  702. end;
  703. function TFPGObjectList.Get(Index: Integer): T;
  704. begin
  705. Result := T(inherited Get(Index)^);
  706. end;
  707. function TFPGObjectList.GetList: PTypeList;
  708. begin
  709. Result := PTypeList(FList);
  710. end;
  711. function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  712. begin
  713. Result := FOnCompare(T(Item1^), T(Item2^));
  714. end;
  715. procedure TFPGObjectList.Put(Index: Integer; const Item: T);
  716. begin
  717. inherited Put(Index, @Item);
  718. end;
  719. function TFPGObjectList.Add(const Item: T): Integer;
  720. begin
  721. Result := inherited Add(@Item);
  722. end;
  723. function TFPGObjectList.Extract(const Item: T): T;
  724. var
  725. ResPtr: Pointer;
  726. begin
  727. ResPtr := inherited Extract(@Item);
  728. if ResPtr <> nil then
  729. Result := T(ResPtr^)
  730. else
  731. FillByte(Result, sizeof(T), 0);
  732. end;
  733. function TFPGObjectList.First: T;
  734. begin
  735. Result := T(inherited First^);
  736. end;
  737. function TFPGObjectList.IndexOf(const Item: T): Integer;
  738. begin
  739. Result := 0;
  740. {$info TODO: fix inlining to work! InternalItems[Result]^}
  741. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  742. Inc(Result);
  743. if Result = FCount then
  744. Result := -1;
  745. end;
  746. procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
  747. begin
  748. T(inherited Insert(Index)^) := Item;
  749. end;
  750. function TFPGObjectList.Last: T;
  751. begin
  752. Result := T(inherited Last^);
  753. end;
  754. function TFPGObjectList.Remove(const Item: T): Integer;
  755. begin
  756. Result := IndexOf(Item);
  757. if Result >= 0 then
  758. Delete(Result);
  759. end;
  760. procedure TFPGObjectList.Sort(Compare: TCompareFunc);
  761. begin
  762. FOnCompare := Compare;
  763. inherited Sort(@ItemPtrCompare);
  764. end;
  765. {****************************************************************************}
  766. {* TFPGInterfacedObjectList *}
  767. {****************************************************************************}
  768. constructor TFPGInterfacedObjectList.Create;
  769. begin
  770. inherited Create;
  771. end;
  772. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  773. begin
  774. T(Dest^) := T(Src^);
  775. if Assigned(Pointer(Dest^)) then
  776. T(Dest^)._AddRef;
  777. end;
  778. procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
  779. begin
  780. if Assigned(Pointer(Item^)) then
  781. T(Item^)._Release;
  782. end;
  783. function TFPGInterfacedObjectList.Get(Index: Integer): T;
  784. begin
  785. Result := T(inherited Get(Index)^);
  786. end;
  787. function TFPGInterfacedObjectList.GetList: PTypeList;
  788. begin
  789. Result := PTypeList(FList);
  790. end;
  791. function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  792. begin
  793. Result := FOnCompare(T(Item1^), T(Item2^));
  794. end;
  795. procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
  796. begin
  797. inherited Put(Index, @Item);
  798. end;
  799. function TFPGInterfacedObjectList.Add(const Item: T): Integer;
  800. begin
  801. Result := inherited Add(@Item);
  802. end;
  803. function TFPGInterfacedObjectList.Extract(const Item: T): T;
  804. var
  805. ResPtr: Pointer;
  806. begin
  807. ResPtr := inherited Extract(@Item);
  808. if ResPtr <> nil then
  809. Result := T(ResPtr^)
  810. else
  811. FillByte(Result, sizeof(T), 0);
  812. end;
  813. function TFPGInterfacedObjectList.First: T;
  814. begin
  815. Result := T(inherited First^);
  816. end;
  817. function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
  818. begin
  819. Result := 0;
  820. {$info TODO: fix inlining to work! InternalItems[Result]^}
  821. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  822. Inc(Result);
  823. if Result = FCount then
  824. Result := -1;
  825. end;
  826. procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
  827. begin
  828. T(inherited Insert(Index)^) := Item;
  829. end;
  830. function TFPGInterfacedObjectList.Last: T;
  831. begin
  832. Result := T(inherited Last^);
  833. end;
  834. function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
  835. begin
  836. Result := IndexOf(Item);
  837. if Result >= 0 then
  838. Delete(Result);
  839. end;
  840. procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
  841. begin
  842. FOnCompare := Compare;
  843. inherited Sort(@ItemPtrCompare);
  844. end;
  845. {$endif}
  846. {****************************************************************************
  847. TFPSMap
  848. ****************************************************************************}
  849. constructor TFPSMap.Create(AKeySize: Integer; ADataSize: integer);
  850. begin
  851. inherited Create(AKeySize+ADataSize);
  852. FKeySize := AKeySize;
  853. FDataSize := ADataSize;
  854. InitOnPtrCompare;
  855. end;
  856. procedure TFPSMap.CopyKey(Src, Dest: Pointer);
  857. begin
  858. System.Move(Src^, Dest^, FKeySize);
  859. end;
  860. procedure TFPSMap.CopyData(Src, Dest: Pointer);
  861. begin
  862. System.Move(Src^, Dest^, FDataSize);
  863. end;
  864. function TFPSMap.GetKey(Index: Integer): Pointer;
  865. begin
  866. Result := Items[Index];
  867. end;
  868. function TFPSMap.GetData(Index: Integer): Pointer;
  869. begin
  870. Result := PByte(Items[Index])+FKeySize;
  871. end;
  872. function TFPSMap.GetKeyData(AKey: Pointer): Pointer;
  873. var
  874. I: Integer;
  875. begin
  876. I := IndexOf(AKey);
  877. if I >= 0 then
  878. Result := InternalItems[I]+FKeySize
  879. else
  880. Error(SMapKeyError, PtrUInt(AKey));
  881. end;
  882. function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer;
  883. begin
  884. Result := CompareByte(Key1^, Key2^, FKeySize);
  885. end;
  886. function TFPSMap.BinaryCompareData(Data1, Data2: Pointer): Integer;
  887. begin
  888. Result := CompareByte(Data1^, Data1^, FDataSize);
  889. end;
  890. procedure TFPSMap.SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
  891. begin
  892. if Proc <> nil then
  893. FOnKeyPtrCompare := Proc
  894. else
  895. FOnKeyPtrCompare := @BinaryCompareKey;
  896. end;
  897. procedure TFPSMap.SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
  898. begin
  899. if Proc <> nil then
  900. FOnDataPtrCompare := Proc
  901. else
  902. FOnDataPtrCompare := @BinaryCompareData;
  903. end;
  904. procedure TFPSMap.InitOnPtrCompare;
  905. begin
  906. SetOnKeyPtrCompare(nil);
  907. SetOnDataPtrCompare(nil);
  908. end;
  909. procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
  910. begin
  911. if FSorted then
  912. Error(SSortedListError, 0);
  913. CopyKey(AKey, Items[Index]);
  914. end;
  915. procedure TFPSMap.PutData(Index: Integer; AData: Pointer);
  916. begin
  917. CopyData(AData, PByte(Items[Index])+FKeySize);
  918. end;
  919. procedure TFPSMap.PutKeyData(AKey: Pointer; NewData: Pointer);
  920. var
  921. I: Integer;
  922. begin
  923. I := IndexOf(AKey);
  924. if I >= 0 then
  925. Data[I] := NewData
  926. else
  927. Add(AKey, NewData);
  928. end;
  929. procedure TFPSMap.SetSorted(Value: Boolean);
  930. begin
  931. if Value = FSorted then exit;
  932. FSorted := Value;
  933. if Value then Sort;
  934. end;
  935. function TFPSMap.Add(AKey: Pointer): Integer;
  936. begin
  937. if Sorted then
  938. begin
  939. if Find(AKey, Result) then
  940. case Duplicates of
  941. dupIgnore: exit;
  942. dupError: Error(SDuplicateItem, 0)
  943. end;
  944. end else
  945. Result := Count;
  946. CopyKey(AKey, inherited Insert(Result));
  947. end;
  948. function TFPSMap.Add(AKey, AData: Pointer): Integer;
  949. begin
  950. Result := Add(AKey);
  951. Data[Result] := AData;
  952. end;
  953. function TFPSMap.Find(AKey: Pointer; out Index: Integer): Boolean;
  954. { Searches for the first item <= Key, returns True if exact match,
  955. sets index to the index f the found string. }
  956. var
  957. I,L,R,Dir: Integer;
  958. begin
  959. Result := false;
  960. // Use binary search.
  961. L := 0;
  962. R := FCount-1;
  963. while L<=R do
  964. begin
  965. I := (L+R) div 2;
  966. Dir := FOnKeyPtrCompare(Items[I], AKey);
  967. if Dir < 0 then
  968. L := I+1
  969. else begin
  970. R := I-1;
  971. if Dir = 0 then
  972. begin
  973. Result := true;
  974. if Duplicates <> dupAccept then
  975. L := I;
  976. end;
  977. end;
  978. end;
  979. Index := L;
  980. end;
  981. function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
  982. var
  983. ListItem: Pointer;
  984. begin
  985. Result := 0;
  986. ListItem := First;
  987. while (Result < FCount) and (FOnKeyPtrCompare(ListItem, AKey) <> 0) do
  988. begin
  989. Inc(Result);
  990. ListItem := PByte(ListItem)+FItemSize;
  991. end;
  992. if Result = FCount then Result := -1;
  993. end;
  994. function TFPSMap.IndexOf(AKey: Pointer): Integer;
  995. begin
  996. if Sorted then
  997. begin
  998. if not Find(AKey, Result) then
  999. Result := -1;
  1000. end else
  1001. Result := LinearIndexOf(AKey);
  1002. end;
  1003. function TFPSMap.IndexOfData(AData: Pointer): Integer;
  1004. var
  1005. ListItem: Pointer;
  1006. begin
  1007. Result := 0;
  1008. ListItem := First+FKeySize;
  1009. while (Result < FCount) and (FOnDataPtrCompare(ListItem, AData) <> 0) do
  1010. begin
  1011. Inc(Result);
  1012. ListItem := PByte(ListItem)+FItemSize;
  1013. end;
  1014. if Result = FCount then Result := -1;
  1015. end;
  1016. function TFPSMap.Insert(Index: Integer): Pointer;
  1017. begin
  1018. if FSorted then
  1019. Error(SSortedListError, 0);
  1020. Result := inherited Insert(Index);
  1021. end;
  1022. procedure TFPSMap.Insert(Index: Integer; out AKey, AData: Pointer);
  1023. begin
  1024. AKey := Insert(Index);
  1025. AData := PByte(AKey) + FKeySize;
  1026. end;
  1027. procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
  1028. begin
  1029. CopyKey(AKey, Insert(Index));
  1030. end;
  1031. procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
  1032. var
  1033. ListItem: Pointer;
  1034. begin
  1035. ListItem := Insert(Index);
  1036. CopyKey(AKey, ListItem);
  1037. CopyData(AData, PByte(ListItem)+FKeySize);
  1038. end;
  1039. function TFPSMap.Remove(AKey: Pointer): Integer;
  1040. begin
  1041. Result := IndexOf(AKey);
  1042. if Result >= 0 then
  1043. Delete(Result);
  1044. end;
  1045. procedure TFPSMap.Sort;
  1046. begin
  1047. inherited Sort(FOnKeyPtrCompare);
  1048. end;
  1049. {****************************************************************************
  1050. TFPGMap
  1051. ****************************************************************************}
  1052. {$ifndef VER2_0}
  1053. constructor TFPGMap.Create;
  1054. begin
  1055. inherited Create(SizeOf(TKey), SizeOf(TData));
  1056. end;
  1057. procedure TFPGMap.CopyItem(Src, Dest: Pointer);
  1058. begin
  1059. CopyKey(Src, Dest);
  1060. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1061. end;
  1062. procedure TFPGMap.CopyKey(Src, Dest: Pointer);
  1063. begin
  1064. TKey(Dest^) := TKey(Src^);
  1065. end;
  1066. procedure TFPGMap.CopyData(Src, Dest: Pointer);
  1067. begin
  1068. TData(Dest^) := TData(Src^);
  1069. end;
  1070. procedure TFPGMap.Deref(Item: Pointer);
  1071. begin
  1072. Finalize(TKey(Item^));
  1073. Finalize(TData(Pointer(PByte(Item)+KeySize)^));
  1074. end;
  1075. function TFPGMap.GetKey(Index: Integer): TKey;
  1076. begin
  1077. Result := TKey(inherited GetKey(Index)^);
  1078. end;
  1079. function TFPGMap.GetData(Index: Integer): TData;
  1080. begin
  1081. Result := TData(inherited GetData(Index)^);
  1082. end;
  1083. function TFPGMap.GetKeyData(const AKey: TKey): TData;
  1084. begin
  1085. Result := TData(inherited GetKeyData(@AKey)^);
  1086. end;
  1087. function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
  1088. begin
  1089. if PKey(Key1)^ < PKey(Key2)^ then
  1090. Result := -1
  1091. else if PKey(Key1)^ > PKey(Key2)^ then
  1092. Result := 1
  1093. else
  1094. Result := 0;
  1095. end;
  1096. {function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
  1097. begin
  1098. if PData(Data1)^ < PData(Data2)^ then
  1099. Result := -1
  1100. else if PData(Data1)^ > PData(Data2)^ then
  1101. Result := 1
  1102. else
  1103. Result := 0;
  1104. end;}
  1105. function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1106. begin
  1107. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1108. end;
  1109. function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1110. begin
  1111. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1112. end;
  1113. procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1114. begin
  1115. FOnKeyCompare := NewCompare;
  1116. if NewCompare <> nil then
  1117. OnKeyPtrCompare := @KeyCustomCompare
  1118. else
  1119. OnKeyPtrCompare := @KeyCompare;
  1120. end;
  1121. procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1122. begin
  1123. FOnDataCompare := NewCompare;
  1124. if NewCompare <> nil then
  1125. OnDataPtrCompare := @DataCustomCompare
  1126. else
  1127. OnDataPtrCompare := nil;
  1128. end;
  1129. procedure TFPGMap.InitOnPtrCompare;
  1130. begin
  1131. SetOnKeyCompare(nil);
  1132. SetOnDataCompare(nil);
  1133. end;
  1134. procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
  1135. begin
  1136. inherited PutKey(Index, @NewKey);
  1137. end;
  1138. procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
  1139. begin
  1140. inherited PutData(Index, @NewData);
  1141. end;
  1142. procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
  1143. begin
  1144. inherited PutKeyData(@AKey, @NewData);
  1145. end;
  1146. function TFPGMap.Add(const AKey: TKey): Integer;
  1147. begin
  1148. Result := inherited Add(@AKey);
  1149. end;
  1150. function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
  1151. begin
  1152. Result := inherited Add(@AKey, @AData);
  1153. end;
  1154. function TFPGMap.Find(const AKey: TKey; out Index: Integer): Boolean;
  1155. begin
  1156. Result := inherited Find(@AKey, Index);
  1157. end;
  1158. function TFPGMap.IndexOf(const AKey: TKey): Integer;
  1159. begin
  1160. Result := inherited IndexOf(@AKey);
  1161. end;
  1162. function TFPGMap.IndexOfData(const AData: TData): Integer;
  1163. begin
  1164. { TODO: loop ? }
  1165. Result := inherited IndexOfData(@AData);
  1166. end;
  1167. procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
  1168. begin
  1169. inherited InsertKey(Index, @AKey);
  1170. end;
  1171. procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1172. begin
  1173. inherited InsertKeyData(Index, @AKey, @AData);
  1174. end;
  1175. function TFPGMap.Remove(const AKey: TKey): Integer;
  1176. begin
  1177. Result := inherited Remove(@AKey);
  1178. end;
  1179. {$endif}
  1180. end.