fgl.pp 57 KB

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