fgl.pp 55 KB

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