fgl.pp 37 KB

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