fgl.pp 55 KB

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