fgl.pp 36 KB

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