fgl.pp 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963
  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 FGLINLINE}
  14. { be aware, this unit is a prototype and subject to be changed heavily }
  15. {$ifdef FGLINLINE}
  16. {$inline on}
  17. {$endif FGLINLINE}
  18. unit fgl;
  19. interface
  20. uses
  21. types, sysutils;
  22. {$IF defined(VER2_4)}
  23. {$DEFINE OldSyntax}
  24. {$IFEND}
  25. const
  26. MaxListSize = Maxint div 16;
  27. type
  28. EListError = class(Exception);
  29. TFPSList = class;
  30. TFPSListCompareFunc = function(Key1, Key2: Pointer): Integer of object;
  31. TFPSList = class(TObject)
  32. protected
  33. FList: PByte;
  34. FCount: Integer;
  35. FCapacity: Integer; { list is one longer sgthan capacity, for temp }
  36. FItemSize: Integer;
  37. procedure CopyItem(Src, Dest: Pointer); virtual;
  38. procedure Deref(Item: Pointer); virtual; overload;
  39. procedure Deref(FromIndex, ToIndex: Integer); overload;
  40. function Get(Index: Integer): Pointer;
  41. procedure InternalExchange(Index1, Index2: Integer);
  42. function InternalGet(Index: Integer): Pointer; {$ifdef FGLINLINE} inline; {$endif}
  43. procedure InternalPut(Index: Integer; NewItem: Pointer);
  44. procedure Put(Index: Integer; Item: Pointer);
  45. procedure QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
  46. procedure SetCapacity(NewCapacity: Integer);
  47. procedure SetCount(NewCount: Integer);
  48. procedure RaiseIndexError(Index : Integer);
  49. property InternalItems[Index: Integer]: Pointer read InternalGet write InternalPut;
  50. function GetLast: Pointer;
  51. procedure SetLast(const Value: Pointer);
  52. function GetFirst: Pointer;
  53. procedure SetFirst(const Value: Pointer);
  54. Procedure CheckIndex(AIndex : Integer); inline;
  55. public
  56. constructor Create(AItemSize: Integer = sizeof(Pointer));
  57. destructor Destroy; override;
  58. function Add(Item: Pointer): Integer;
  59. procedure Clear;
  60. procedure Delete(Index: Integer);
  61. class procedure Error(const Msg: string; Data: PtrInt);
  62. procedure Exchange(Index1, Index2: Integer);
  63. function Expand: TFPSList;
  64. procedure Extract(Item: Pointer; ResultPtr: Pointer);
  65. function IndexOf(Item: Pointer): Integer;
  66. procedure Insert(Index: Integer; Item: Pointer);
  67. function Insert(Index: Integer): Pointer;
  68. procedure Move(CurIndex, NewIndex: Integer);
  69. procedure Assign(Obj: TFPSList);
  70. function Remove(Item: Pointer): Integer;
  71. procedure Pack;
  72. procedure Sort(Compare: TFPSListCompareFunc);
  73. property Capacity: Integer read FCapacity write SetCapacity;
  74. property Count: Integer read FCount write SetCount;
  75. property Items[Index: Integer]: Pointer read Get write Put; default;
  76. property ItemSize: Integer read FItemSize;
  77. property List: PByte read FList;
  78. property First: Pointer read GetFirst write SetFirst;
  79. property Last: Pointer read GetLast write SetLast;
  80. end;
  81. const
  82. {$ifdef cpu16}
  83. MaxGListSize = {MaxInt div} 1024;
  84. {$else cpu16}
  85. MaxGListSize = MaxInt div 1024;
  86. {$endif cpu16}
  87. type
  88. generic TFPGListEnumerator<T> = class(TObject)
  89. protected
  90. FList: TFPSList;
  91. FPosition: Integer;
  92. function GetCurrent: T;
  93. public
  94. constructor Create(AList: TFPSList);
  95. function MoveNext: Boolean;
  96. property Current: T read GetCurrent;
  97. end;
  98. generic TFPGList<T> = class(TFPSList)
  99. private
  100. type
  101. TCompareFunc = function(const Item1, Item2: T): Integer;
  102. TTypeList = array[0..MaxGListSize] of T;
  103. PTypeList = ^TTypeList;
  104. PT = ^T;
  105. {$ifndef OldSyntax}protected var{$else}var protected{$endif}
  106. FOnCompare: TCompareFunc;
  107. procedure CopyItem(Src, Dest: Pointer); override;
  108. procedure Deref(Item: Pointer); override;
  109. function Get(Index: Integer): T; {$ifdef FGLINLINE} inline; {$endif}
  110. function GetList: PTypeList; {$ifdef FGLINLINE} inline; {$endif}
  111. function ItemPtrCompare(Item1, Item2: Pointer): Integer;
  112. procedure Put(Index: Integer; const Item: T); {$ifdef FGLINLINE} inline; {$endif}
  113. function GetLast: T; {$ifdef FGLINLINE} inline; {$endif}
  114. procedure SetLast(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
  115. function GetFirst: T; {$ifdef FGLINLINE} inline; {$endif}
  116. procedure SetFirst(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
  117. public
  118. Type
  119. TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
  120. constructor Create;
  121. function Add(const Item: T): Integer; {$ifdef FGLINLINE} inline; {$endif}
  122. function Extract(const Item: T): T; {$ifdef FGLINLINE} inline; {$endif}
  123. property First: T read GetFirst write SetFirst;
  124. function GetEnumerator: TFPGListEnumeratorSpec; {$ifdef FGLINLINE} inline; {$endif}
  125. function IndexOf(const Item: T): Integer;
  126. procedure Insert(Index: Integer; const Item: T); {$ifdef FGLINLINE} inline; {$endif}
  127. property Last: T read GetLast write SetLast;
  128. {$ifndef VER2_4}
  129. procedure Assign(Source: TFPGList);
  130. {$endif VER2_4}
  131. function Remove(const Item: T): Integer; {$ifdef FGLINLINE} inline; {$endif}
  132. procedure Sort(Compare: TCompareFunc);
  133. property Items[Index: Integer]: T read Get write Put; default;
  134. property List: PTypeList read GetList;
  135. end;
  136. generic TFPGObjectList<T> = class(TFPSList)
  137. private
  138. type
  139. TCompareFunc = function(const Item1, Item2: T): Integer;
  140. TTypeList = array[0..MaxGListSize] of T;
  141. PTypeList = ^TTypeList;
  142. PT = ^T;
  143. TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
  144. {$ifndef OldSyntax}protected var{$else}var protected{$endif}
  145. FOnCompare: TCompareFunc;
  146. FFreeObjects: Boolean;
  147. procedure CopyItem(Src, Dest: Pointer); override;
  148. procedure Deref(Item: Pointer); override;
  149. function Get(Index: Integer): T; {$ifdef FGLINLINE} inline; {$endif}
  150. function GetList: PTypeList; {$ifdef FGLINLINE} inline; {$endif}
  151. function ItemPtrCompare(Item1, Item2: Pointer): Integer;
  152. procedure Put(Index: Integer; const Item: T); {$ifdef FGLINLINE} inline; {$endif}
  153. function GetLast: T; {$ifdef FGLINLINE} inline; {$endif}
  154. procedure SetLast(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
  155. function GetFirst: T; {$ifdef FGLINLINE} inline; {$endif}
  156. procedure SetFirst(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
  157. public
  158. constructor Create(FreeObjects: Boolean = True);
  159. function Add(const Item: T): Integer; {$ifdef FGLINLINE} inline; {$endif}
  160. function Extract(const Item: T): T; {$ifdef FGLINLINE} inline; {$endif}
  161. property First: T read GetFirst write SetFirst;
  162. function GetEnumerator: TFPGListEnumeratorSpec; {$ifdef FGLINLINE} inline; {$endif}
  163. function IndexOf(const Item: T): Integer;
  164. procedure Insert(Index: Integer; const Item: T); {$ifdef FGLINLINE} inline; {$endif}
  165. property Last: T read GetLast write SetLast;
  166. {$ifndef VER2_4}
  167. procedure Assign(Source: TFPGObjectList);
  168. {$endif VER2_4}
  169. function Remove(const Item: T): Integer; {$ifdef FGLINLINE} inline; {$endif}
  170. procedure Sort(Compare: TCompareFunc);
  171. property Items[Index: Integer]: T read Get write Put; default;
  172. property List: PTypeList read GetList;
  173. property FreeObjects: Boolean read FFreeObjects write FFreeObjects;
  174. end;
  175. generic TFPGInterfacedObjectList<T> = class(TFPSList)
  176. private
  177. type
  178. TCompareFunc = function(const Item1, Item2: T): Integer;
  179. TTypeList = array[0..MaxGListSize] of T;
  180. PTypeList = ^TTypeList;
  181. PT = ^T;
  182. TFPGListEnumeratorSpec = specialize TFPGListEnumerator<T>;
  183. {$ifndef OldSyntax}protected var{$else}var protected{$endif}
  184. FOnCompare: TCompareFunc;
  185. procedure CopyItem(Src, Dest: Pointer); override;
  186. procedure Deref(Item: Pointer); override;
  187. function Get(Index: Integer): T; {$ifdef FGLINLINE} inline; {$endif}
  188. function GetList: PTypeList; {$ifdef FGLINLINE} inline; {$endif}
  189. function ItemPtrCompare(Item1, Item2: Pointer): Integer;
  190. procedure Put(Index: Integer; const Item: T); {$ifdef FGLINLINE} inline; {$endif}
  191. function GetLast: T; {$ifdef FGLINLINE} inline; {$endif}
  192. procedure SetLast(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
  193. function GetFirst: T; {$ifdef FGLINLINE} inline; {$endif}
  194. procedure SetFirst(const Value: T); {$ifdef FGLINLINE} inline; {$endif}
  195. public
  196. constructor Create;
  197. function Add(const Item: T): Integer; {$ifdef FGLINLINE} inline; {$endif}
  198. function Extract(const Item: T): T; {$ifdef FGLINLINE} inline; {$endif}
  199. property First: T read GetFirst write SetFirst;
  200. function GetEnumerator: TFPGListEnumeratorSpec; {$ifdef FGLINLINE} inline; {$endif}
  201. function IndexOf(const Item: T): Integer;
  202. procedure Insert(Index: Integer; const Item: T); {$ifdef FGLINLINE} inline; {$endif}
  203. property Last: T read GetLast write SetLast;
  204. {$ifndef VER2_4}
  205. procedure Assign(Source: TFPGInterfacedObjectList);
  206. {$endif VER2_4}
  207. function Remove(const Item: T): Integer; {$ifdef FGLINLINE} inline; {$endif}
  208. procedure Sort(Compare: TCompareFunc);
  209. property Items[Index: Integer]: T read Get write Put; default;
  210. property List: PTypeList read GetList;
  211. end;
  212. TFPSMap = class(TFPSList)
  213. private
  214. FKeySize: Integer;
  215. FDataSize: Integer;
  216. FDuplicates: TDuplicates;
  217. FSorted: Boolean;
  218. FOnKeyPtrCompare: TFPSListCompareFunc;
  219. FOnDataPtrCompare: TFPSListCompareFunc;
  220. procedure SetSorted(Value: Boolean);
  221. protected
  222. function BinaryCompareKey(Key1, Key2: Pointer): Integer;
  223. function BinaryCompareData(Data1, Data2: Pointer): Integer;
  224. procedure SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
  225. procedure SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
  226. procedure InitOnPtrCompare; virtual;
  227. procedure CopyKey(Src, Dest: Pointer); virtual;
  228. procedure CopyData(Src, Dest: Pointer); virtual;
  229. function GetKey(Index: Integer): Pointer;
  230. function GetKeyData(AKey: Pointer): Pointer;
  231. function GetData(Index: Integer): Pointer;
  232. function LinearIndexOf(AKey: Pointer): Integer;
  233. procedure PutKey(Index: Integer; AKey: Pointer);
  234. procedure PutKeyData(AKey: Pointer; NewData: Pointer);
  235. procedure PutData(Index: Integer; AData: Pointer);
  236. public
  237. constructor Create(AKeySize: Integer = sizeof(Pointer);
  238. ADataSize: integer = sizeof(Pointer));
  239. function Add(AKey, AData: Pointer): Integer;
  240. function Add(AKey: Pointer): Integer;
  241. function Find(AKey: Pointer; out Index: Integer): Boolean;
  242. function IndexOf(AKey: Pointer): Integer;
  243. function IndexOfData(AData: Pointer): Integer;
  244. function Insert(Index: Integer): Pointer;
  245. procedure Insert(Index: Integer; out AKey, AData: Pointer);
  246. procedure InsertKey(Index: Integer; AKey: Pointer);
  247. procedure InsertKeyData(Index: Integer; AKey, AData: Pointer);
  248. function Remove(AKey: Pointer): Integer;
  249. procedure Sort;
  250. property Duplicates: TDuplicates read FDuplicates write FDuplicates;
  251. property KeySize: Integer read FKeySize;
  252. property DataSize: Integer read FDataSize;
  253. property Keys[Index: Integer]: Pointer read GetKey write PutKey;
  254. property Data[Index: Integer]: Pointer read GetData write PutData;
  255. property KeyData[Key: Pointer]: Pointer read GetKeyData write PutKeyData; default;
  256. property Sorted: Boolean read FSorted write SetSorted;
  257. property OnPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare; //deprecated;
  258. property OnKeyPtrCompare: TFPSListCompareFunc read FOnKeyPtrCompare write SetOnKeyPtrCompare;
  259. property OnDataPtrCompare: TFPSListCompareFunc read FOnDataPtrCompare write SetOnDataPtrCompare;
  260. end;
  261. generic TFPGMap<TKey, TData> = class(TFPSMap)
  262. private
  263. type
  264. TKeyCompareFunc = function(const Key1, Key2: TKey): Integer;
  265. TDataCompareFunc = function(const Data1, Data2: TData): Integer;
  266. PKey = ^TKey;
  267. // unsed PData = ^TData;
  268. {$ifndef OldSyntax}protected var{$else}var protected{$endif}
  269. FOnKeyCompare: TKeyCompareFunc;
  270. FOnDataCompare: TDataCompareFunc;
  271. procedure CopyItem(Src, Dest: Pointer); override;
  272. procedure CopyKey(Src, Dest: Pointer); override;
  273. procedure CopyData(Src, Dest: Pointer); override;
  274. procedure Deref(Item: Pointer); override;
  275. procedure InitOnPtrCompare; override;
  276. function GetKey(Index: Integer): TKey; {$ifdef FGLINLINE} inline; {$endif}
  277. function GetKeyData(const AKey: TKey): TData; {$ifdef FGLINLINE} inline; {$endif}
  278. function GetData(Index: Integer): TData; {$ifdef FGLINLINE} inline; {$endif}
  279. function KeyCompare(Key1, Key2: Pointer): Integer;
  280. function KeyCustomCompare(Key1, Key2: Pointer): Integer;
  281. //function DataCompare(Data1, Data2: Pointer): Integer;
  282. function DataCustomCompare(Data1, Data2: Pointer): Integer;
  283. procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef FGLINLINE} inline; {$endif}
  284. procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef FGLINLINE} inline; {$endif}
  285. procedure PutData(Index: Integer; const NewData: TData); {$ifdef FGLINLINE} inline; {$endif}
  286. procedure SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  287. procedure SetOnDataCompare(NewCompare: TDataCompareFunc);
  288. public
  289. constructor Create;
  290. function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef FGLINLINE} inline; {$endif}
  291. function Add(const AKey: TKey): Integer; {$ifdef FGLINLINE} inline; {$endif}
  292. function Find(const AKey: TKey; out Index: Integer): Boolean; {$ifdef FGLINLINE} inline; {$endif}
  293. function TryGetData(const AKey: TKey; out AData: TData): Boolean; {$ifdef FGLINLINE} inline; {$endif}
  294. procedure AddOrSetData(const AKey: TKey; const AData: TData); {$ifdef FGLINLINE} inline; {$endif}
  295. function IndexOf(const AKey: TKey): Integer; {$ifdef FGLINLINE} inline; {$endif}
  296. function IndexOfData(const AData: TData): Integer;
  297. procedure InsertKey(Index: Integer; const AKey: TKey);
  298. procedure InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  299. function Remove(const AKey: TKey): Integer;
  300. property Keys[Index: Integer]: TKey read GetKey write PutKey;
  301. property Data[Index: Integer]: TData read GetData write PutData;
  302. property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
  303. property OnCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare; //deprecated;
  304. property OnKeyCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare;
  305. property OnDataCompare: TDataCompareFunc read FOnDataCompare write SetOnDataCompare;
  306. end;
  307. generic TFPGMapObject<TKey, TData> = class(TFPSMap)
  308. private
  309. type
  310. TKeyCompareFunc = function(const Key1, Key2: TKey): Integer;
  311. TDataCompareFunc = function(const Data1, Data2: TData): Integer;
  312. PKey = ^TKey;
  313. // unsed PData = ^TData;
  314. {$ifndef OldSyntax}protected var{$else}var protected{$endif}
  315. FOnKeyCompare: TKeyCompareFunc;
  316. FOnDataCompare: TDataCompareFunc;
  317. FFreeObjects: Boolean;
  318. procedure CopyItem(Src, Dest: Pointer); override;
  319. procedure CopyKey(Src, Dest: Pointer); override;
  320. procedure CopyData(Src, Dest: Pointer); override;
  321. procedure Deref(Item: Pointer); override;
  322. procedure InitOnPtrCompare; override;
  323. function GetKey(Index: Integer): TKey; {$ifdef FGLINLINE} inline; {$endif}
  324. function GetKeyData(const AKey: TKey): TData; {$ifdef FGLINLINE} inline; {$endif}
  325. function GetData(Index: Integer): TData; {$ifdef FGLINLINE} inline; {$endif}
  326. function KeyCompare(Key1, Key2: Pointer): Integer;
  327. function KeyCustomCompare(Key1, Key2: Pointer): Integer;
  328. //function DataCompare(Data1, Data2: Pointer): Integer;
  329. function DataCustomCompare(Data1, Data2: Pointer): Integer;
  330. procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef FGLINLINE} inline; {$endif}
  331. procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef FGLINLINE} inline; {$endif}
  332. procedure PutData(Index: Integer; const NewData: TData); {$ifdef FGLINLINE} inline; {$endif}
  333. procedure SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  334. procedure SetOnDataCompare(NewCompare: TDataCompareFunc);
  335. public
  336. constructor Create(AFreeObjects: Boolean);
  337. constructor Create;
  338. function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef FGLINLINE} inline; {$endif}
  339. function Add(const AKey: TKey): Integer; {$ifdef FGLINLINE} inline; {$endif}
  340. function Find(const AKey: TKey; out Index: Integer): Boolean; {$ifdef FGLINLINE} inline; {$endif}
  341. function TryGetData(const AKey: TKey; out AData: TData): Boolean; {$ifdef FGLINLINE} inline; {$endif}
  342. procedure AddOrSetData(const AKey: TKey; const AData: TData); {$ifdef FGLINLINE} inline; {$endif}
  343. function IndexOf(const AKey: TKey): Integer; {$ifdef FGLINLINE} inline; {$endif}
  344. function IndexOfData(const AData: TData): Integer;
  345. procedure InsertKey(Index: Integer; const AKey: TKey);
  346. procedure InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  347. function Remove(const AKey: TKey): Integer;
  348. property Keys[Index: Integer]: TKey read GetKey write PutKey;
  349. property Data[Index: Integer]: TData read GetData write PutData;
  350. property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
  351. property OnCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare; //deprecated;
  352. property OnKeyCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare;
  353. property OnDataCompare: TDataCompareFunc read FOnDataCompare write SetOnDataCompare;
  354. end;
  355. generic TFPGMapInterfacedObjectData<TKey, TData> = class(TFPSMap)
  356. private
  357. type
  358. TKeyCompareFunc = function(const Key1, Key2: TKey): Integer;
  359. TDataCompareFunc = function(const Data1, Data2: TData): Integer;
  360. PKey = ^TKey;
  361. // unsed PData = ^TData;
  362. {$ifndef OldSyntax}protected var{$else}var protected{$endif}
  363. FOnKeyCompare: TKeyCompareFunc;
  364. FOnDataCompare: TDataCompareFunc;
  365. procedure CopyItem(Src, Dest: Pointer); override;
  366. procedure CopyKey(Src, Dest: Pointer); override;
  367. procedure CopyData(Src, Dest: Pointer); override;
  368. procedure Deref(Item: Pointer); override;
  369. procedure InitOnPtrCompare; override;
  370. function GetKey(Index: Integer): TKey; {$ifdef FGLINLINE} inline; {$endif}
  371. function GetKeyData(const AKey: TKey): TData; {$ifdef FGLINLINE} inline; {$endif}
  372. function GetData(Index: Integer): TData; {$ifdef FGLINLINE} inline; {$endif}
  373. function KeyCompare(Key1, Key2: Pointer): Integer;
  374. function KeyCustomCompare(Key1, Key2: Pointer): Integer;
  375. //function DataCompare(Data1, Data2: Pointer): Integer;
  376. function DataCustomCompare(Data1, Data2: Pointer): Integer;
  377. procedure PutKey(Index: Integer; const NewKey: TKey); {$ifdef FGLINLINE} inline; {$endif}
  378. procedure PutKeyData(const AKey: TKey; const NewData: TData); {$ifdef FGLINLINE} inline; {$endif}
  379. procedure PutData(Index: Integer; const NewData: TData); {$ifdef FGLINLINE} inline; {$endif}
  380. procedure SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  381. procedure SetOnDataCompare(NewCompare: TDataCompareFunc);
  382. public
  383. constructor Create;
  384. function Add(const AKey: TKey; const AData: TData): Integer; {$ifdef FGLINLINE} inline; {$endif}
  385. function Add(const AKey: TKey): Integer; {$ifdef FGLINLINE} inline; {$endif}
  386. function Find(const AKey: TKey; out Index: Integer): Boolean; {$ifdef FGLINLINE} inline; {$endif}
  387. function TryGetData(const AKey: TKey; out AData: TData): Boolean; {$ifdef FGLINLINE} inline; {$endif}
  388. procedure AddOrSetData(const AKey: TKey; const AData: TData); {$ifdef FGLINLINE} inline; {$endif}
  389. function IndexOf(const AKey: TKey): Integer; {$ifdef FGLINLINE} inline; {$endif}
  390. function IndexOfData(const AData: TData): Integer;
  391. procedure InsertKey(Index: Integer; const AKey: TKey);
  392. procedure InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  393. function Remove(const AKey: TKey): Integer;
  394. property Keys[Index: Integer]: TKey read GetKey write PutKey;
  395. property Data[Index: Integer]: TData read GetData write PutData;
  396. property KeyData[const AKey: TKey]: TData read GetKeyData write PutKeyData; default;
  397. property OnCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare; //deprecated;
  398. property OnKeyCompare: TKeyCompareFunc read FOnKeyCompare write SetOnKeyCompare;
  399. property OnDataCompare: TDataCompareFunc read FOnDataCompare write SetOnDataCompare;
  400. end;
  401. implementation
  402. uses
  403. rtlconsts;
  404. {****************************************************************************
  405. TFPSList
  406. ****************************************************************************}
  407. constructor TFPSList.Create(AItemSize: integer);
  408. begin
  409. inherited Create;
  410. FItemSize := AItemSize;
  411. end;
  412. destructor TFPSList.Destroy;
  413. begin
  414. Clear;
  415. // Clear() does not clear the whole list; there is always a single temp entry
  416. // at the end which is never freed. Take care of that one here.
  417. FreeMem(FList);
  418. inherited Destroy;
  419. end;
  420. procedure TFPSList.CopyItem(Src, Dest: Pointer);
  421. begin
  422. System.Move(Src^, Dest^, FItemSize);
  423. end;
  424. procedure TFPSList.RaiseIndexError(Index : Integer);
  425. begin
  426. Error(SListIndexError, Index);
  427. end;
  428. function TFPSList.InternalGet(Index: Integer): Pointer;
  429. begin
  430. Result:=FList+Index*ItemSize;
  431. end;
  432. procedure TFPSList.InternalPut(Index: Integer; NewItem: Pointer);
  433. var
  434. ListItem: Pointer;
  435. begin
  436. ListItem := InternalItems[Index];
  437. CopyItem(NewItem, ListItem);
  438. end;
  439. function TFPSList.Get(Index: Integer): Pointer;
  440. begin
  441. CheckIndex(Index);
  442. Result := InternalItems[Index];
  443. end;
  444. procedure TFPSList.Put(Index: Integer; Item: Pointer);
  445. var p : Pointer;
  446. begin
  447. CheckIndex(Index);
  448. p:=InternalItems[Index];
  449. if assigned(p) then
  450. DeRef(p);
  451. InternalItems[Index] := Item;
  452. end;
  453. procedure TFPSList.SetCapacity(NewCapacity: Integer);
  454. begin
  455. if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
  456. Error(SListCapacityError, NewCapacity);
  457. if NewCapacity = FCapacity then
  458. exit;
  459. ReallocMem(FList, (NewCapacity+1) * FItemSize);
  460. FillChar(InternalItems[FCapacity]^, (NewCapacity+1-FCapacity) * FItemSize, #0);
  461. FCapacity := NewCapacity;
  462. end;
  463. procedure TFPSList.Deref(Item: Pointer);
  464. begin
  465. end;
  466. procedure TFPSList.Deref(FromIndex, ToIndex: Integer);
  467. var
  468. ListItem, ListItemLast: Pointer;
  469. begin
  470. ListItem := InternalItems[FromIndex];
  471. ListItemLast := InternalItems[ToIndex];
  472. repeat
  473. Deref(ListItem);
  474. if ListItem = ListItemLast then
  475. break;
  476. ListItem := PByte(ListItem) + ItemSize;
  477. until false;
  478. end;
  479. procedure TFPSList.SetCount(NewCount: Integer);
  480. begin
  481. if (NewCount < 0) or (NewCount > MaxListSize) then
  482. Error(SListCountError, NewCount);
  483. if NewCount > FCapacity then
  484. SetCapacity(NewCount);
  485. if NewCount > FCount then
  486. FillByte(InternalItems[FCount]^, (NewCount-FCount) * FItemSize, 0)
  487. else if NewCount < FCount then
  488. Deref(NewCount, FCount-1);
  489. FCount := NewCount;
  490. end;
  491. function TFPSList.Add(Item: Pointer): Integer;
  492. begin
  493. if FCount = FCapacity then
  494. Self.Expand;
  495. CopyItem(Item, InternalItems[FCount]);
  496. Result := FCount;
  497. Inc(FCount);
  498. end;
  499. procedure TFPSList.CheckIndex(AIndex : Integer);
  500. begin
  501. if (AIndex < 0) or (AIndex >= FCount) then
  502. Error(SListIndexError, AIndex);
  503. end;
  504. procedure TFPSList.Clear;
  505. begin
  506. if Assigned(FList) then
  507. begin
  508. SetCount(0);
  509. SetCapacity(0);
  510. end;
  511. end;
  512. procedure TFPSList.Delete(Index: Integer);
  513. var
  514. ListItem: Pointer;
  515. begin
  516. CheckIndex(Index);
  517. Dec(FCount);
  518. ListItem := InternalItems[Index];
  519. Deref(ListItem);
  520. System.Move(InternalItems[Index+1]^, ListItem^, (FCount - Index) * FItemSize);
  521. // Shrink the list if appropriate
  522. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  523. begin
  524. FCapacity := FCapacity shr 1;
  525. ReallocMem(FList, (FCapacity+1) * FItemSize);
  526. end;
  527. { Keep the ending of the list filled with zeros, don't leave garbage data
  528. there. Otherwise, we could accidentally have there a copy of some item
  529. on the list, and accidentally Deref it too soon.
  530. See http://bugs.freepascal.org/view.php?id=20005. }
  531. FillChar(InternalItems[FCount]^, (FCapacity+1-FCount) * FItemSize, #0);
  532. end;
  533. procedure TFPSList.Extract(Item: Pointer; ResultPtr: Pointer);
  534. var
  535. i : Integer;
  536. ListItemPtr : Pointer;
  537. begin
  538. i := IndexOf(Item);
  539. if i >= 0 then
  540. begin
  541. ListItemPtr := InternalItems[i];
  542. System.Move(ListItemPtr^, ResultPtr^, FItemSize);
  543. { fill with zeros, to avoid freeing/decreasing reference on following Delete }
  544. System.FillByte(ListItemPtr^, FItemSize, 0);
  545. Delete(i);
  546. end else
  547. System.FillByte(ResultPtr^, FItemSize, 0);
  548. end;
  549. class procedure TFPSList.Error(const Msg: string; Data: PtrInt);
  550. begin
  551. raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame), get_caller_frame(get_frame);
  552. end;
  553. procedure TFPSList.Exchange(Index1, Index2: Integer);
  554. begin
  555. CheckIndex(Index1);
  556. CheckIndex(Index2);
  557. InternalExchange(Index1, Index2);
  558. end;
  559. procedure TFPSList.InternalExchange(Index1, Index2: Integer);
  560. begin
  561. System.Move(InternalItems[Index1]^, InternalItems[FCapacity]^, FItemSize);
  562. System.Move(InternalItems[Index2]^, InternalItems[Index1]^, FItemSize);
  563. System.Move(InternalItems[FCapacity]^, InternalItems[Index2]^, FItemSize);
  564. end;
  565. function TFPSList.Expand: TFPSList;
  566. var
  567. IncSize : Longint;
  568. begin
  569. if FCount < FCapacity then exit;
  570. IncSize := 4;
  571. if FCapacity > 3 then IncSize := IncSize + 4;
  572. if FCapacity > 8 then IncSize := IncSize + 8;
  573. if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
  574. SetCapacity(FCapacity + IncSize);
  575. Result := Self;
  576. end;
  577. function TFPSList.GetFirst: Pointer;
  578. begin
  579. If FCount = 0 then
  580. Result := Nil
  581. else
  582. Result := InternalItems[0];
  583. end;
  584. procedure TFPSList.SetFirst(const Value: Pointer);
  585. begin
  586. Put(0, Value);
  587. end;
  588. function TFPSList.IndexOf(Item: Pointer): Integer;
  589. var
  590. ListItem: Pointer;
  591. begin
  592. Result := 0;
  593. ListItem := First;
  594. while (Result < FCount) and (CompareByte(ListItem^, Item^, FItemSize) <> 0) do
  595. begin
  596. Inc(Result);
  597. ListItem := PByte(ListItem)+FItemSize;
  598. end;
  599. if Result = FCount then Result := -1;
  600. end;
  601. function TFPSList.Insert(Index: Integer): Pointer;
  602. begin
  603. if (Index < 0) or (Index > FCount) then
  604. Error(SListIndexError, Index);
  605. if FCount = FCapacity then Self.Expand;
  606. Result := InternalItems[Index];
  607. if Index<FCount then
  608. begin
  609. System.Move(Result^, (Result+FItemSize)^, (FCount - Index) * FItemSize);
  610. { clear for compiler assisted types }
  611. System.FillByte(Result^, FItemSize, 0);
  612. end;
  613. Inc(FCount);
  614. end;
  615. procedure TFPSList.Insert(Index: Integer; Item: Pointer);
  616. begin
  617. CopyItem(Item, Insert(Index));
  618. end;
  619. function TFPSList.GetLast: Pointer;
  620. begin
  621. if FCount = 0 then
  622. Result := nil
  623. else
  624. Result := InternalItems[FCount - 1];
  625. end;
  626. procedure TFPSList.SetLast(const Value: Pointer);
  627. begin
  628. Put(FCount - 1, Value);
  629. end;
  630. procedure TFPSList.Move(CurIndex, NewIndex: Integer);
  631. var
  632. CurItem, NewItem, TmpItem, Src, Dest: Pointer;
  633. MoveCount: Integer;
  634. begin
  635. CheckIndex(CurIndex);
  636. CheckIndex(NewIndex);
  637. if CurIndex = NewIndex then
  638. exit;
  639. CurItem := InternalItems[CurIndex];
  640. NewItem := InternalItems[NewIndex];
  641. TmpItem := InternalItems[FCapacity];
  642. System.Move(CurItem^, TmpItem^, FItemSize);
  643. if NewIndex > CurIndex then
  644. begin
  645. Src := InternalItems[CurIndex+1];
  646. Dest := CurItem;
  647. MoveCount := NewIndex - CurIndex;
  648. end else begin
  649. Src := NewItem;
  650. Dest := InternalItems[NewIndex+1];
  651. MoveCount := CurIndex - NewIndex;
  652. end;
  653. System.Move(Src^, Dest^, MoveCount * FItemSize);
  654. System.Move(TmpItem^, NewItem^, FItemSize);
  655. end;
  656. function TFPSList.Remove(Item: Pointer): Integer;
  657. begin
  658. Result := IndexOf(Item);
  659. if Result <> -1 then
  660. Delete(Result);
  661. end;
  662. const LocalThreshold = 64;
  663. procedure TFPSList.Pack;
  664. var
  665. LItemSize : integer;
  666. NewCount,
  667. i : integer;
  668. pdest,
  669. psrc : Pointer;
  670. localnul : array[0..LocalThreshold-1] of byte;
  671. pnul : pointer;
  672. begin
  673. LItemSize:=FItemSize;
  674. pnul:=@localnul;
  675. if LItemSize>Localthreshold then
  676. getmem(pnul,LItemSize);
  677. fillchar(pnul^,LItemSize,#0);
  678. NewCount:=0;
  679. psrc:=First;
  680. pdest:=psrc;
  681. For I:=0 To FCount-1 Do
  682. begin
  683. if not CompareMem(psrc,pnul,LItemSize) then
  684. begin
  685. System.Move(psrc^, pdest^, LItemSize);
  686. inc(pdest,LItemSIze);
  687. inc(NewCount);
  688. end
  689. else
  690. deref(psrc);
  691. inc(psrc,LitemSize);
  692. end;
  693. if LItemSize>Localthreshold then
  694. FreeMem(pnul,LItemSize);
  695. FCount:=NewCount;
  696. end;
  697. // Needed by Sort method.
  698. procedure TFPSList.QuickSort(L, R: Integer; Compare: TFPSListCompareFunc);
  699. var
  700. I, J, P: Integer;
  701. PivotItem: Pointer;
  702. begin
  703. repeat
  704. I := L;
  705. J := R;
  706. { cast to dword to avoid overflow to a negative number during addition which
  707. would result again in a negative number when being divided }
  708. P := (dword(L) + dword(R)) div 2;
  709. repeat
  710. PivotItem := InternalItems[P];
  711. while Compare(PivotItem, InternalItems[I]) > 0 do
  712. Inc(I);
  713. while Compare(PivotItem, InternalItems[J]) < 0 do
  714. Dec(J);
  715. if I <= J then
  716. begin
  717. InternalExchange(I, J);
  718. if P = I then
  719. P := J
  720. else if P = J then
  721. P := I;
  722. Inc(I);
  723. Dec(J);
  724. end;
  725. until I > J;
  726. if L < J then
  727. QuickSort(L, J, Compare);
  728. L := I;
  729. until I >= R;
  730. end;
  731. procedure TFPSList.Sort(Compare: TFPSListCompareFunc);
  732. begin
  733. if not Assigned(FList) or (FCount < 2) then exit;
  734. QuickSort(0, FCount-1, Compare);
  735. end;
  736. procedure TFPSList.Assign(Obj: TFPSList);
  737. var
  738. i: Integer;
  739. begin
  740. if Obj.ItemSize <> FItemSize then
  741. Error(SListItemSizeError, 0);
  742. Clear;
  743. for I := 0 to Obj.Count - 1 do
  744. Add(Obj[i]);
  745. end;
  746. {****************************************************************************}
  747. {* TFPGListEnumerator *}
  748. {****************************************************************************}
  749. function TFPGListEnumerator.GetCurrent: T;
  750. begin
  751. Result := T(FList.Items[FPosition]^);
  752. end;
  753. constructor TFPGListEnumerator.Create(AList: TFPSList);
  754. begin
  755. inherited Create;
  756. FList := AList;
  757. FPosition := -1;
  758. end;
  759. function TFPGListEnumerator.MoveNext: Boolean;
  760. begin
  761. inc(FPosition);
  762. Result := FPosition < FList.Count;
  763. end;
  764. {****************************************************************************}
  765. {* TFPGList *}
  766. {****************************************************************************}
  767. constructor TFPGList.Create;
  768. begin
  769. inherited Create(sizeof(T));
  770. end;
  771. procedure TFPGList.CopyItem(Src, Dest: Pointer);
  772. begin
  773. T(Dest^) := T(Src^);
  774. end;
  775. procedure TFPGList.Deref(Item: Pointer);
  776. begin
  777. Finalize(T(Item^));
  778. end;
  779. function TFPGList.Get(Index: Integer): T;
  780. begin
  781. Result := T(inherited Get(Index)^);
  782. end;
  783. function TFPGList.GetList: PTypeList;
  784. begin
  785. Result := PTypeList(FList);
  786. end;
  787. function TFPGList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  788. begin
  789. Result := FOnCompare(T(Item1^), T(Item2^));
  790. end;
  791. procedure TFPGList.Put(Index: Integer; const Item: T);
  792. begin
  793. inherited Put(Index, @Item);
  794. end;
  795. function TFPGList.Add(const Item: T): Integer;
  796. begin
  797. Result := inherited Add(@Item);
  798. end;
  799. function TFPGList.Extract(const Item: T): T;
  800. begin
  801. inherited Extract(@Item, @Result);
  802. end;
  803. function TFPGList.GetFirst: T;
  804. begin
  805. if FCount<>0 then
  806. Result := T(inherited GetFirst^)
  807. else
  808. Result:=Default(T);
  809. end;
  810. procedure TFPGList.SetFirst(const Value: T);
  811. begin
  812. inherited SetFirst(@Value);
  813. end;
  814. function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
  815. begin
  816. Result := TFPGListEnumeratorSpec.Create(Self);
  817. end;
  818. function TFPGList.IndexOf(const Item: T): Integer;
  819. begin
  820. Result := 0;
  821. {$info TODO: fix inlining to work! InternalItems[Result]^}
  822. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  823. Inc(Result);
  824. if Result = FCount then
  825. Result := -1;
  826. end;
  827. procedure TFPGList.Insert(Index: Integer; const Item: T);
  828. begin
  829. T(inherited Insert(Index)^) := Item;
  830. end;
  831. function TFPGList.GetLast: T;
  832. begin
  833. if FCount<>0 then
  834. Result := T(inherited GetLast^)
  835. else
  836. result:=Default(T);
  837. end;
  838. procedure TFPGList.SetLast(const Value: T);
  839. begin
  840. inherited SetLast(@Value);
  841. end;
  842. {$ifndef VER2_4}
  843. procedure TFPGList.Assign(Source: TFPGList);
  844. var
  845. i: Integer;
  846. begin
  847. Clear;
  848. for I := 0 to Source.Count - 1 do
  849. Add(Source[i]);
  850. end;
  851. {$endif VER2_4}
  852. function TFPGList.Remove(const Item: T): Integer;
  853. begin
  854. Result := IndexOf(Item);
  855. if Result >= 0 then
  856. Delete(Result);
  857. end;
  858. procedure TFPGList.Sort(Compare: TCompareFunc);
  859. begin
  860. FOnCompare := Compare;
  861. inherited Sort(@ItemPtrCompare);
  862. end;
  863. {****************************************************************************}
  864. {* TFPGObjectList *}
  865. {****************************************************************************}
  866. constructor TFPGObjectList.Create(FreeObjects: Boolean);
  867. begin
  868. inherited Create;
  869. FFreeObjects := FreeObjects;
  870. end;
  871. procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
  872. begin
  873. T(Dest^) := T(Src^);
  874. end;
  875. procedure TFPGObjectList.Deref(Item: Pointer);
  876. begin
  877. if FFreeObjects then
  878. T(Item^).Free;
  879. end;
  880. function TFPGObjectList.Get(Index: Integer): T;
  881. begin
  882. Result := T(inherited Get(Index)^);
  883. end;
  884. function TFPGObjectList.GetList: PTypeList;
  885. begin
  886. Result := PTypeList(FList);
  887. end;
  888. function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  889. begin
  890. Result := FOnCompare(T(Item1^), T(Item2^));
  891. end;
  892. procedure TFPGObjectList.Put(Index: Integer; const Item: T);
  893. begin
  894. inherited Put(Index, @Item);
  895. end;
  896. function TFPGObjectList.Add(const Item: T): Integer;
  897. begin
  898. Result := inherited Add(@Item);
  899. end;
  900. function TFPGObjectList.Extract(const Item: T): T;
  901. begin
  902. inherited Extract(@Item, @Result);
  903. end;
  904. function TFPGObjectList.GetFirst: T;
  905. begin
  906. Result := T(inherited GetFirst^);
  907. end;
  908. procedure TFPGObjectList.SetFirst(const Value: T);
  909. begin
  910. inherited SetFirst(@Value);
  911. end;
  912. function TFPGObjectList.GetEnumerator: TFPGListEnumeratorSpec;
  913. begin
  914. Result := TFPGListEnumeratorSpec.Create(Self);
  915. end;
  916. function TFPGObjectList.IndexOf(const Item: T): Integer;
  917. begin
  918. Result := 0;
  919. {$info TODO: fix inlining to work! InternalItems[Result]^}
  920. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  921. Inc(Result);
  922. if Result = FCount then
  923. Result := -1;
  924. end;
  925. procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
  926. begin
  927. T(inherited Insert(Index)^) := Item;
  928. end;
  929. function TFPGObjectList.GetLast: T;
  930. begin
  931. Result := T(inherited GetLast^);
  932. end;
  933. procedure TFPGObjectList.SetLast(const Value: T);
  934. begin
  935. inherited SetLast(@Value);
  936. end;
  937. {$ifndef VER2_4}
  938. procedure TFPGObjectList.Assign(Source: TFPGObjectList);
  939. var
  940. i: Integer;
  941. begin
  942. Clear;
  943. for I := 0 to Source.Count - 1 do
  944. Add(Source[i]);
  945. end;
  946. {$endif VER2_4}
  947. function TFPGObjectList.Remove(const Item: T): Integer;
  948. begin
  949. Result := IndexOf(Item);
  950. if Result >= 0 then
  951. Delete(Result);
  952. end;
  953. procedure TFPGObjectList.Sort(Compare: TCompareFunc);
  954. begin
  955. FOnCompare := Compare;
  956. inherited Sort(@ItemPtrCompare);
  957. end;
  958. {****************************************************************************}
  959. {* TFPGInterfacedObjectList *}
  960. {****************************************************************************}
  961. constructor TFPGInterfacedObjectList.Create;
  962. begin
  963. inherited Create;
  964. end;
  965. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  966. begin
  967. if Assigned(Pointer(Dest^)) then
  968. T(Dest^)._Release;
  969. Pointer(Dest^) := Pointer(Src^);
  970. if Assigned(Pointer(Dest^)) then
  971. T(Dest^)._AddRef;
  972. end;
  973. procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
  974. begin
  975. if Assigned(Pointer(Item^)) then
  976. T(Item^)._Release;
  977. end;
  978. function TFPGInterfacedObjectList.Get(Index: Integer): T;
  979. begin
  980. Result := T(inherited Get(Index)^);
  981. end;
  982. function TFPGInterfacedObjectList.GetList: PTypeList;
  983. begin
  984. Result := PTypeList(FList);
  985. end;
  986. function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  987. begin
  988. Result := FOnCompare(T(Item1^), T(Item2^));
  989. end;
  990. procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
  991. begin
  992. inherited Put(Index, @Item);
  993. end;
  994. function TFPGInterfacedObjectList.Add(const Item: T): Integer;
  995. begin
  996. Result := inherited Add(@Item);
  997. end;
  998. function TFPGInterfacedObjectList.Extract(const Item: T): T;
  999. begin
  1000. inherited Extract(@Item, @Result);
  1001. end;
  1002. function TFPGInterfacedObjectList.GetFirst: T;
  1003. begin
  1004. Result := T(inherited GetFirst^);
  1005. end;
  1006. procedure TFPGInterfacedObjectList.SetFirst(const Value: T);
  1007. begin
  1008. inherited SetFirst(@Value);
  1009. end;
  1010. function TFPGInterfacedObjectList.GetEnumerator: TFPGListEnumeratorSpec;
  1011. begin
  1012. Result := TFPGListEnumeratorSpec.Create(Self);
  1013. end;
  1014. function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
  1015. begin
  1016. Result := 0;
  1017. {$info TODO: fix inlining to work! InternalItems[Result]^}
  1018. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  1019. Inc(Result);
  1020. if Result = FCount then
  1021. Result := -1;
  1022. end;
  1023. procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
  1024. begin
  1025. T(inherited Insert(Index)^) := Item;
  1026. end;
  1027. function TFPGInterfacedObjectList.GetLast: T;
  1028. begin
  1029. Result := T(inherited GetLast^);
  1030. end;
  1031. procedure TFPGInterfacedObjectList.SetLast(const Value: T);
  1032. begin
  1033. inherited SetLast(@Value);
  1034. end;
  1035. {$ifndef VER2_4}
  1036. procedure TFPGInterfacedObjectList.Assign(Source: TFPGInterfacedObjectList);
  1037. var
  1038. i: Integer;
  1039. begin
  1040. Clear;
  1041. for I := 0 to Source.Count - 1 do
  1042. Add(Source[i]);
  1043. end;
  1044. {$endif VER2_4}
  1045. function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
  1046. begin
  1047. Result := IndexOf(Item);
  1048. if Result >= 0 then
  1049. Delete(Result);
  1050. end;
  1051. procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
  1052. begin
  1053. FOnCompare := Compare;
  1054. inherited Sort(@ItemPtrCompare);
  1055. end;
  1056. {****************************************************************************
  1057. TFPSMap
  1058. ****************************************************************************}
  1059. constructor TFPSMap.Create(AKeySize: Integer; ADataSize: integer);
  1060. begin
  1061. inherited Create(AKeySize+ADataSize);
  1062. FKeySize := AKeySize;
  1063. FDataSize := ADataSize;
  1064. InitOnPtrCompare;
  1065. end;
  1066. procedure TFPSMap.CopyKey(Src, Dest: Pointer);
  1067. begin
  1068. System.Move(Src^, Dest^, FKeySize);
  1069. end;
  1070. procedure TFPSMap.CopyData(Src, Dest: Pointer);
  1071. begin
  1072. System.Move(Src^, Dest^, FDataSize);
  1073. end;
  1074. function TFPSMap.GetKey(Index: Integer): Pointer;
  1075. begin
  1076. Result := Items[Index];
  1077. end;
  1078. function TFPSMap.GetData(Index: Integer): Pointer;
  1079. begin
  1080. Result := PByte(Items[Index])+FKeySize;
  1081. end;
  1082. function TFPSMap.GetKeyData(AKey: Pointer): Pointer;
  1083. var
  1084. I: Integer;
  1085. begin
  1086. I := IndexOf(AKey);
  1087. if I >= 0 then
  1088. Result := InternalItems[I]+FKeySize
  1089. else
  1090. Error(SMapKeyError, PtrUInt(AKey));
  1091. end;
  1092. function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer;
  1093. begin
  1094. Result := CompareByte(Key1^, Key2^, FKeySize);
  1095. end;
  1096. function TFPSMap.BinaryCompareData(Data1, Data2: Pointer): Integer;
  1097. begin
  1098. Result := CompareByte(Data1^, Data2^, FDataSize);
  1099. end;
  1100. procedure TFPSMap.SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
  1101. begin
  1102. if Proc <> nil then
  1103. FOnKeyPtrCompare := Proc
  1104. else
  1105. FOnKeyPtrCompare := @BinaryCompareKey;
  1106. end;
  1107. procedure TFPSMap.SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
  1108. begin
  1109. if Proc <> nil then
  1110. FOnDataPtrCompare := Proc
  1111. else
  1112. FOnDataPtrCompare := @BinaryCompareData;
  1113. end;
  1114. procedure TFPSMap.InitOnPtrCompare;
  1115. begin
  1116. SetOnKeyPtrCompare(nil);
  1117. SetOnDataPtrCompare(nil);
  1118. end;
  1119. procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
  1120. begin
  1121. if FSorted then
  1122. Error(SSortedListError, 0);
  1123. CopyKey(AKey, Items[Index]);
  1124. end;
  1125. procedure TFPSMap.PutData(Index: Integer; AData: Pointer);
  1126. begin
  1127. CopyData(AData, PByte(Items[Index])+FKeySize);
  1128. end;
  1129. procedure TFPSMap.PutKeyData(AKey: Pointer; NewData: Pointer);
  1130. var
  1131. I: Integer;
  1132. begin
  1133. I := IndexOf(AKey);
  1134. if I >= 0 then
  1135. Data[I] := NewData
  1136. else
  1137. Add(AKey, NewData);
  1138. end;
  1139. procedure TFPSMap.SetSorted(Value: Boolean);
  1140. begin
  1141. if Value = FSorted then exit;
  1142. FSorted := Value;
  1143. if Value then Sort;
  1144. end;
  1145. function TFPSMap.Add(AKey: Pointer): Integer;
  1146. begin
  1147. if Sorted then
  1148. begin
  1149. if Find(AKey, Result) then
  1150. case Duplicates of
  1151. dupIgnore: exit;
  1152. dupError: Error(SDuplicateItem, 0)
  1153. end;
  1154. end else
  1155. Result := Count;
  1156. CopyKey(AKey, inherited Insert(Result));
  1157. end;
  1158. function TFPSMap.Add(AKey, AData: Pointer): Integer;
  1159. begin
  1160. Result := Add(AKey);
  1161. Data[Result] := AData;
  1162. end;
  1163. function TFPSMap.Find(AKey: Pointer; out Index: Integer): Boolean;
  1164. { Searches for the first item <= Key, returns True if exact match,
  1165. sets index to the index of the found string. }
  1166. var
  1167. I,L,R,Dir: Integer;
  1168. begin
  1169. Result := false;
  1170. // Use binary search.
  1171. L := 0;
  1172. R := FCount-1;
  1173. while L<=R do
  1174. begin
  1175. I := L + (R - L) div 2;
  1176. Dir := FOnKeyPtrCompare(Items[I], AKey);
  1177. if Dir < 0 then
  1178. L := I+1
  1179. else begin
  1180. R := I-1;
  1181. if Dir = 0 then
  1182. begin
  1183. Result := true;
  1184. if Duplicates <> dupAccept then
  1185. L := I;
  1186. end;
  1187. end;
  1188. end;
  1189. Index := L;
  1190. end;
  1191. function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
  1192. var
  1193. ListItem: Pointer;
  1194. begin
  1195. Result := 0;
  1196. ListItem := First;
  1197. while (Result < FCount) and (FOnKeyPtrCompare(ListItem, AKey) <> 0) do
  1198. begin
  1199. Inc(Result);
  1200. ListItem := PByte(ListItem)+FItemSize;
  1201. end;
  1202. if Result = FCount then Result := -1;
  1203. end;
  1204. function TFPSMap.IndexOf(AKey: Pointer): Integer;
  1205. begin
  1206. if Sorted then
  1207. begin
  1208. if not Find(AKey, Result) then
  1209. Result := -1;
  1210. end else
  1211. Result := LinearIndexOf(AKey);
  1212. end;
  1213. function TFPSMap.IndexOfData(AData: Pointer): Integer;
  1214. var
  1215. ListItem: Pointer;
  1216. begin
  1217. Result := 0;
  1218. ListItem := First+FKeySize;
  1219. while (Result < FCount) and (FOnDataPtrCompare(ListItem, AData) <> 0) do
  1220. begin
  1221. Inc(Result);
  1222. ListItem := PByte(ListItem)+FItemSize;
  1223. end;
  1224. if Result = FCount then Result := -1;
  1225. end;
  1226. function TFPSMap.Insert(Index: Integer): Pointer;
  1227. begin
  1228. if FSorted then
  1229. Error(SSortedListError, 0);
  1230. Result := inherited Insert(Index);
  1231. end;
  1232. procedure TFPSMap.Insert(Index: Integer; out AKey, AData: Pointer);
  1233. begin
  1234. AKey := Insert(Index);
  1235. AData := PByte(AKey) + FKeySize;
  1236. end;
  1237. procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
  1238. begin
  1239. CopyKey(AKey, Insert(Index));
  1240. end;
  1241. procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
  1242. var
  1243. ListItem: Pointer;
  1244. begin
  1245. ListItem := Insert(Index);
  1246. CopyKey(AKey, ListItem);
  1247. CopyData(AData, PByte(ListItem)+FKeySize);
  1248. end;
  1249. function TFPSMap.Remove(AKey: Pointer): Integer;
  1250. begin
  1251. Result := IndexOf(AKey);
  1252. if Result >= 0 then
  1253. Delete(Result);
  1254. end;
  1255. procedure TFPSMap.Sort;
  1256. begin
  1257. inherited Sort(FOnKeyPtrCompare);
  1258. end;
  1259. {****************************************************************************
  1260. TFPGMap
  1261. ****************************************************************************}
  1262. constructor TFPGMap.Create;
  1263. begin
  1264. inherited Create(SizeOf(TKey), SizeOf(TData));
  1265. end;
  1266. procedure TFPGMap.CopyItem(Src, Dest: Pointer);
  1267. begin
  1268. CopyKey(Src, Dest);
  1269. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1270. end;
  1271. procedure TFPGMap.CopyKey(Src, Dest: Pointer);
  1272. begin
  1273. TKey(Dest^) := TKey(Src^);
  1274. end;
  1275. procedure TFPGMap.CopyData(Src, Dest: Pointer);
  1276. begin
  1277. TData(Dest^) := TData(Src^);
  1278. end;
  1279. procedure TFPGMap.Deref(Item: Pointer);
  1280. begin
  1281. Finalize(TKey(Item^));
  1282. Finalize(TData(Pointer(PByte(Item)+KeySize)^));
  1283. end;
  1284. function TFPGMap.GetKey(Index: Integer): TKey;
  1285. begin
  1286. Result := TKey(inherited GetKey(Index)^);
  1287. end;
  1288. function TFPGMap.GetData(Index: Integer): TData;
  1289. begin
  1290. Result := TData(inherited GetData(Index)^);
  1291. end;
  1292. function TFPGMap.GetKeyData(const AKey: TKey): TData;
  1293. begin
  1294. Result := TData(inherited GetKeyData(@AKey)^);
  1295. end;
  1296. function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
  1297. begin
  1298. if PKey(Key1)^ < PKey(Key2)^ then
  1299. Result := -1
  1300. else if PKey(Key1)^ > PKey(Key2)^ then
  1301. Result := 1
  1302. else
  1303. Result := 0;
  1304. end;
  1305. {function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
  1306. begin
  1307. if PData(Data1)^ < PData(Data2)^ then
  1308. Result := -1
  1309. else if PData(Data1)^ > PData(Data2)^ then
  1310. Result := 1
  1311. else
  1312. Result := 0;
  1313. end;}
  1314. function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1315. begin
  1316. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1317. end;
  1318. function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1319. begin
  1320. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1321. end;
  1322. procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1323. begin
  1324. FOnKeyCompare := NewCompare;
  1325. if NewCompare <> nil then
  1326. OnKeyPtrCompare := @KeyCustomCompare
  1327. else
  1328. OnKeyPtrCompare := @KeyCompare;
  1329. end;
  1330. procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1331. begin
  1332. FOnDataCompare := NewCompare;
  1333. if NewCompare <> nil then
  1334. OnDataPtrCompare := @DataCustomCompare
  1335. else
  1336. OnDataPtrCompare := nil;
  1337. end;
  1338. procedure TFPGMap.InitOnPtrCompare;
  1339. begin
  1340. SetOnKeyCompare(nil);
  1341. SetOnDataCompare(nil);
  1342. end;
  1343. procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
  1344. begin
  1345. inherited PutKey(Index, @NewKey);
  1346. end;
  1347. procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
  1348. begin
  1349. inherited PutData(Index, @NewData);
  1350. end;
  1351. procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
  1352. begin
  1353. inherited PutKeyData(@AKey, @NewData);
  1354. end;
  1355. function TFPGMap.Add(const AKey: TKey): Integer;
  1356. begin
  1357. Result := inherited Add(@AKey);
  1358. end;
  1359. function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
  1360. begin
  1361. Result := inherited Add(@AKey, @AData);
  1362. end;
  1363. function TFPGMap.Find(const AKey: TKey; out Index: Integer): Boolean;
  1364. begin
  1365. Result := inherited Find(@AKey, Index);
  1366. end;
  1367. function TFPGMap.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1368. var
  1369. I: Integer;
  1370. begin
  1371. Result := inherited Find(@AKey, I);
  1372. if Result then
  1373. AData := TData(inherited GetData(I)^)
  1374. else
  1375. {$IFDEF VER2_6}
  1376. FillChar(AData,SizeOf(TData),0);
  1377. {$ELSE}
  1378. AData := Default(TData);
  1379. {$ENDIF}
  1380. end;
  1381. procedure TFPGMap.AddOrSetData(const AKey: TKey; const AData: TData);
  1382. begin
  1383. inherited PutKeyData(@AKey, @AData);
  1384. end;
  1385. function TFPGMap.IndexOf(const AKey: TKey): Integer;
  1386. begin
  1387. Result := inherited IndexOf(@AKey);
  1388. end;
  1389. function TFPGMap.IndexOfData(const AData: TData): Integer;
  1390. begin
  1391. { TODO: loop ? }
  1392. Result := inherited IndexOfData(@AData);
  1393. end;
  1394. procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
  1395. begin
  1396. inherited InsertKey(Index, @AKey);
  1397. end;
  1398. procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1399. begin
  1400. inherited InsertKeyData(Index, @AKey, @AData);
  1401. end;
  1402. function TFPGMap.Remove(const AKey: TKey): Integer;
  1403. begin
  1404. Result := inherited Remove(@AKey);
  1405. end;
  1406. {****************************************************************************
  1407. TFPGMapObject
  1408. ****************************************************************************}
  1409. constructor TFPGMapObject.Create(AFreeObjects: Boolean);
  1410. begin
  1411. inherited Create(SizeOf(TKey), SizeOf(TData));
  1412. FFreeObjects := AFreeObjects;
  1413. end;
  1414. constructor TFPGMapObject.Create;
  1415. begin
  1416. Create(True);
  1417. end;
  1418. procedure TFPGMapObject.CopyItem(Src, Dest: Pointer);
  1419. begin
  1420. CopyKey(Src, Dest);
  1421. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1422. end;
  1423. procedure TFPGMapObject.CopyKey(Src, Dest: Pointer);
  1424. begin
  1425. TKey(Dest^) := TKey(Src^);
  1426. end;
  1427. procedure TFPGMapObject.CopyData(Src, Dest: Pointer);
  1428. begin
  1429. if Assigned(Pointer(Dest^)) then
  1430. TData(Dest^).Free;
  1431. TData(Dest^) := TData(Src^);
  1432. end;
  1433. procedure TFPGMapObject.Deref(Item: Pointer);
  1434. begin
  1435. Finalize(TKey(Item^));
  1436. if Assigned(PPointer(PByte(Item)+KeySize)^) and FFreeObjects then
  1437. TData(Pointer(PByte(Item)+KeySize)^).Free;
  1438. end;
  1439. function TFPGMapObject.GetKey(Index: Integer): TKey;
  1440. begin
  1441. Result := TKey(inherited GetKey(Index)^);
  1442. end;
  1443. function TFPGMapObject.GetData(Index: Integer): TData;
  1444. begin
  1445. Result := TData(inherited GetData(Index)^);
  1446. end;
  1447. function TFPGMapObject.GetKeyData(const AKey: TKey): TData;
  1448. begin
  1449. Result := TData(inherited GetKeyData(@AKey)^);
  1450. end;
  1451. function TFPGMapObject.KeyCompare(Key1, Key2: Pointer): Integer;
  1452. begin
  1453. if PKey(Key1)^ < PKey(Key2)^ then
  1454. Result := -1
  1455. else if PKey(Key1)^ > PKey(Key2)^ then
  1456. Result := 1
  1457. else
  1458. Result := 0;
  1459. end;
  1460. {function TFPGMapObject.DataCompare(Data1, Data2: Pointer): Integer;
  1461. begin
  1462. if PData(Data1)^ < PData(Data2)^ then
  1463. Result := -1
  1464. else if PData(Data1)^ > PData(Data2)^ then
  1465. Result := 1
  1466. else
  1467. Result := 0;
  1468. end;}
  1469. function TFPGMapObject.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1470. begin
  1471. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1472. end;
  1473. function TFPGMapObject.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1474. begin
  1475. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1476. end;
  1477. procedure TFPGMapObject.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1478. begin
  1479. FOnKeyCompare := NewCompare;
  1480. if NewCompare <> nil then
  1481. OnKeyPtrCompare := @KeyCustomCompare
  1482. else
  1483. OnKeyPtrCompare := @KeyCompare;
  1484. end;
  1485. procedure TFPGMapObject.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1486. begin
  1487. FOnDataCompare := NewCompare;
  1488. if NewCompare <> nil then
  1489. OnDataPtrCompare := @DataCustomCompare
  1490. else
  1491. OnDataPtrCompare := nil;
  1492. end;
  1493. procedure TFPGMapObject.InitOnPtrCompare;
  1494. begin
  1495. SetOnKeyCompare(nil);
  1496. SetOnDataCompare(nil);
  1497. end;
  1498. procedure TFPGMapObject.PutKey(Index: Integer; const NewKey: TKey);
  1499. begin
  1500. inherited PutKey(Index, @NewKey);
  1501. end;
  1502. procedure TFPGMapObject.PutData(Index: Integer; const NewData: TData);
  1503. begin
  1504. inherited PutData(Index, @NewData);
  1505. end;
  1506. procedure TFPGMapObject.PutKeyData(const AKey: TKey; const NewData: TData);
  1507. begin
  1508. inherited PutKeyData(@AKey, @NewData);
  1509. end;
  1510. function TFPGMapObject.Add(const AKey: TKey): Integer;
  1511. begin
  1512. Result := inherited Add(@AKey);
  1513. end;
  1514. function TFPGMapObject.Add(const AKey: TKey; const AData: TData): Integer;
  1515. begin
  1516. Result := inherited Add(@AKey, @AData);
  1517. end;
  1518. function TFPGMapObject.Find(const AKey: TKey; out Index: Integer): Boolean;
  1519. begin
  1520. Result := inherited Find(@AKey, Index);
  1521. end;
  1522. function TFPGMapObject.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1523. var
  1524. I: Integer;
  1525. begin
  1526. Result := inherited Find(@AKey, I);
  1527. if Result then
  1528. AData := TData(inherited GetData(I)^)
  1529. else
  1530. {$IFDEF VER2_6}
  1531. FillChar(AData,SizeOf(TData),0);
  1532. {$ELSE}
  1533. AData := Default(TData);
  1534. {$ENDIF}
  1535. end;
  1536. procedure TFPGMapObject.AddOrSetData(const AKey: TKey; const AData: TData);
  1537. begin
  1538. inherited PutKeyData(@AKey, @AData);
  1539. end;
  1540. function TFPGMapObject.IndexOf(const AKey: TKey): Integer;
  1541. begin
  1542. Result := inherited IndexOf(@AKey);
  1543. end;
  1544. function TFPGMapObject.IndexOfData(const AData: TData): Integer;
  1545. begin
  1546. { TODO: loop ? }
  1547. Result := inherited IndexOfData(@AData);
  1548. end;
  1549. procedure TFPGMapObject.InsertKey(Index: Integer; const AKey: TKey);
  1550. begin
  1551. inherited InsertKey(Index, @AKey);
  1552. end;
  1553. procedure TFPGMapObject.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1554. begin
  1555. inherited InsertKeyData(Index, @AKey, @AData);
  1556. end;
  1557. function TFPGMapObject.Remove(const AKey: TKey): Integer;
  1558. begin
  1559. Result := inherited Remove(@AKey);
  1560. end;
  1561. {****************************************************************************
  1562. TFPGMapInterfacedObjectData
  1563. ****************************************************************************}
  1564. constructor TFPGMapInterfacedObjectData.Create;
  1565. begin
  1566. inherited Create(SizeOf(TKey), SizeOf(TData));
  1567. end;
  1568. procedure TFPGMapInterfacedObjectData.CopyItem(Src, Dest: Pointer);
  1569. begin
  1570. CopyKey(Src, Dest);
  1571. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1572. end;
  1573. procedure TFPGMapInterfacedObjectData.CopyKey(Src, Dest: Pointer);
  1574. begin
  1575. TKey(Dest^) := TKey(Src^);
  1576. end;
  1577. procedure TFPGMapInterfacedObjectData.CopyData(Src, Dest: Pointer);
  1578. begin
  1579. if Assigned(Pointer(Dest^)) then
  1580. TData(Dest^)._Release;
  1581. TData(Dest^) := TData(Src^);
  1582. if Assigned(Pointer(Dest^)) then
  1583. TData(Dest^)._AddRef;
  1584. end;
  1585. procedure TFPGMapInterfacedObjectData.Deref(Item: Pointer);
  1586. begin
  1587. Finalize(TKey(Item^));
  1588. if Assigned(PPointer(PByte(Item)+KeySize)^) then
  1589. TData(Pointer(PByte(Item)+KeySize)^)._Release;
  1590. end;
  1591. function TFPGMapInterfacedObjectData.GetKey(Index: Integer): TKey;
  1592. begin
  1593. Result := TKey(inherited GetKey(Index)^);
  1594. end;
  1595. function TFPGMapInterfacedObjectData.GetData(Index: Integer): TData;
  1596. begin
  1597. Result := TData(inherited GetData(Index)^);
  1598. end;
  1599. function TFPGMapInterfacedObjectData.GetKeyData(const AKey: TKey): TData;
  1600. begin
  1601. Result := TData(inherited GetKeyData(@AKey)^);
  1602. end;
  1603. function TFPGMapInterfacedObjectData.KeyCompare(Key1, Key2: Pointer): Integer;
  1604. begin
  1605. if PKey(Key1)^ < PKey(Key2)^ then
  1606. Result := -1
  1607. else if PKey(Key1)^ > PKey(Key2)^ then
  1608. Result := 1
  1609. else
  1610. Result := 0;
  1611. end;
  1612. {function TFPGMapInterfacedObjectData.DataCompare(Data1, Data2: Pointer): Integer;
  1613. begin
  1614. if PData(Data1)^ < PData(Data2)^ then
  1615. Result := -1
  1616. else if PData(Data1)^ > PData(Data2)^ then
  1617. Result := 1
  1618. else
  1619. Result := 0;
  1620. end;}
  1621. function TFPGMapInterfacedObjectData.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1622. begin
  1623. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1624. end;
  1625. function TFPGMapInterfacedObjectData.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1626. begin
  1627. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1628. end;
  1629. procedure TFPGMapInterfacedObjectData.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1630. begin
  1631. FOnKeyCompare := NewCompare;
  1632. if NewCompare <> nil then
  1633. OnKeyPtrCompare := @KeyCustomCompare
  1634. else
  1635. OnKeyPtrCompare := @KeyCompare;
  1636. end;
  1637. procedure TFPGMapInterfacedObjectData.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1638. begin
  1639. FOnDataCompare := NewCompare;
  1640. if NewCompare <> nil then
  1641. OnDataPtrCompare := @DataCustomCompare
  1642. else
  1643. OnDataPtrCompare := nil;
  1644. end;
  1645. procedure TFPGMapInterfacedObjectData.InitOnPtrCompare;
  1646. begin
  1647. SetOnKeyCompare(nil);
  1648. SetOnDataCompare(nil);
  1649. end;
  1650. procedure TFPGMapInterfacedObjectData.PutKey(Index: Integer; const NewKey: TKey);
  1651. begin
  1652. inherited PutKey(Index, @NewKey);
  1653. end;
  1654. procedure TFPGMapInterfacedObjectData.PutData(Index: Integer; const NewData: TData);
  1655. begin
  1656. inherited PutData(Index, @NewData);
  1657. end;
  1658. procedure TFPGMapInterfacedObjectData.PutKeyData(const AKey: TKey; const NewData: TData);
  1659. begin
  1660. inherited PutKeyData(@AKey, @NewData);
  1661. end;
  1662. function TFPGMapInterfacedObjectData.Add(const AKey: TKey): Integer;
  1663. begin
  1664. Result := inherited Add(@AKey);
  1665. end;
  1666. function TFPGMapInterfacedObjectData.Add(const AKey: TKey; const AData: TData): Integer;
  1667. begin
  1668. Result := inherited Add(@AKey, @AData);
  1669. end;
  1670. function TFPGMapInterfacedObjectData.Find(const AKey: TKey; out Index: Integer): Boolean;
  1671. begin
  1672. Result := inherited Find(@AKey, Index);
  1673. end;
  1674. function TFPGMapInterfacedObjectData.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1675. var
  1676. I: Integer;
  1677. begin
  1678. Result := inherited Find(@AKey, I);
  1679. if Result then
  1680. AData := TData(inherited GetData(I)^)
  1681. else
  1682. {$IFDEF VER2_6}
  1683. FillChar(AData,SizeOf(TData),0);
  1684. {$ELSE}
  1685. AData := Default(TData);
  1686. {$ENDIF}
  1687. end;
  1688. procedure TFPGMapInterfacedObjectData.AddOrSetData(const AKey: TKey;
  1689. const AData: TData);
  1690. begin
  1691. inherited PutKeyData(@AKey, @AData);
  1692. end;
  1693. function TFPGMapInterfacedObjectData.IndexOf(const AKey: TKey): Integer;
  1694. begin
  1695. Result := inherited IndexOf(@AKey);
  1696. end;
  1697. function TFPGMapInterfacedObjectData.IndexOfData(const AData: TData): Integer;
  1698. begin
  1699. { TODO: loop ? }
  1700. Result := inherited IndexOfData(@AData);
  1701. end;
  1702. procedure TFPGMapInterfacedObjectData.InsertKey(Index: Integer; const AKey: TKey);
  1703. begin
  1704. inherited InsertKey(Index, @AKey);
  1705. end;
  1706. procedure TFPGMapInterfacedObjectData.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1707. begin
  1708. inherited InsertKeyData(Index, @AKey, @AData);
  1709. end;
  1710. function TFPGMapInterfacedObjectData.Remove(const AKey: TKey): Integer;
  1711. begin
  1712. Result := inherited Remove(@AKey);
  1713. end;
  1714. end.