fgl.pp 56 KB

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