fgl.pp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968
  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. Index := -1;
  1170. if not Sorted then
  1171. raise EListError.Create(SErrFindNeedsSortedList);
  1172. // Use binary search.
  1173. L := 0;
  1174. R := FCount-1;
  1175. while L<=R do
  1176. begin
  1177. I := L + (R - L) div 2;
  1178. Dir := FOnKeyPtrCompare(Items[I], AKey);
  1179. if Dir < 0 then
  1180. L := I+1
  1181. else begin
  1182. R := I-1;
  1183. if Dir = 0 then
  1184. begin
  1185. Result := true;
  1186. if Duplicates <> dupAccept then
  1187. L := I;
  1188. end;
  1189. end;
  1190. end;
  1191. Index := L;
  1192. end;
  1193. function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
  1194. var
  1195. ListItem: Pointer;
  1196. begin
  1197. Result := 0;
  1198. ListItem := First;
  1199. while (Result < FCount) and (FOnKeyPtrCompare(ListItem, AKey) <> 0) do
  1200. begin
  1201. Inc(Result);
  1202. ListItem := PByte(ListItem)+FItemSize;
  1203. end;
  1204. if Result = FCount then Result := -1;
  1205. end;
  1206. function TFPSMap.IndexOf(AKey: Pointer): Integer;
  1207. begin
  1208. if Sorted then
  1209. begin
  1210. if not Find(AKey, Result) then
  1211. Result := -1;
  1212. end else
  1213. Result := LinearIndexOf(AKey);
  1214. end;
  1215. function TFPSMap.IndexOfData(AData: Pointer): Integer;
  1216. var
  1217. ListItem: Pointer;
  1218. begin
  1219. Result := 0;
  1220. ListItem := First+FKeySize;
  1221. while (Result < FCount) and (FOnDataPtrCompare(ListItem, AData) <> 0) do
  1222. begin
  1223. Inc(Result);
  1224. ListItem := PByte(ListItem)+FItemSize;
  1225. end;
  1226. if Result = FCount then Result := -1;
  1227. end;
  1228. function TFPSMap.Insert(Index: Integer): Pointer;
  1229. begin
  1230. if FSorted then
  1231. Error(SSortedListError, 0);
  1232. Result := inherited Insert(Index);
  1233. end;
  1234. procedure TFPSMap.Insert(Index: Integer; out AKey, AData: Pointer);
  1235. begin
  1236. AKey := Insert(Index);
  1237. AData := PByte(AKey) + FKeySize;
  1238. end;
  1239. procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
  1240. begin
  1241. CopyKey(AKey, Insert(Index));
  1242. end;
  1243. procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
  1244. var
  1245. ListItem: Pointer;
  1246. begin
  1247. ListItem := Insert(Index);
  1248. CopyKey(AKey, ListItem);
  1249. CopyData(AData, PByte(ListItem)+FKeySize);
  1250. end;
  1251. function TFPSMap.Remove(AKey: Pointer): Integer;
  1252. begin
  1253. Result := IndexOf(AKey);
  1254. if Result >= 0 then
  1255. Delete(Result);
  1256. end;
  1257. procedure TFPSMap.Sort;
  1258. begin
  1259. inherited Sort(FOnKeyPtrCompare);
  1260. end;
  1261. {****************************************************************************
  1262. TFPGMap
  1263. ****************************************************************************}
  1264. constructor TFPGMap.Create;
  1265. begin
  1266. inherited Create(SizeOf(TKey), SizeOf(TData));
  1267. end;
  1268. procedure TFPGMap.CopyItem(Src, Dest: Pointer);
  1269. begin
  1270. CopyKey(Src, Dest);
  1271. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1272. end;
  1273. procedure TFPGMap.CopyKey(Src, Dest: Pointer);
  1274. begin
  1275. TKey(Dest^) := TKey(Src^);
  1276. end;
  1277. procedure TFPGMap.CopyData(Src, Dest: Pointer);
  1278. begin
  1279. TData(Dest^) := TData(Src^);
  1280. end;
  1281. procedure TFPGMap.Deref(Item: Pointer);
  1282. begin
  1283. Finalize(TKey(Item^));
  1284. Finalize(TData(Pointer(PByte(Item)+KeySize)^));
  1285. end;
  1286. function TFPGMap.GetKey(Index: Integer): TKey;
  1287. begin
  1288. Result := TKey(inherited GetKey(Index)^);
  1289. end;
  1290. function TFPGMap.GetData(Index: Integer): TData;
  1291. begin
  1292. Result := TData(inherited GetData(Index)^);
  1293. end;
  1294. function TFPGMap.GetKeyData(const AKey: TKey): TData;
  1295. begin
  1296. Result := TData(inherited GetKeyData(@AKey)^);
  1297. end;
  1298. function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
  1299. begin
  1300. if PKey(Key1)^ < PKey(Key2)^ then
  1301. Result := -1
  1302. else if PKey(Key1)^ > PKey(Key2)^ then
  1303. Result := 1
  1304. else
  1305. Result := 0;
  1306. end;
  1307. {function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
  1308. begin
  1309. if PData(Data1)^ < PData(Data2)^ then
  1310. Result := -1
  1311. else if PData(Data1)^ > PData(Data2)^ then
  1312. Result := 1
  1313. else
  1314. Result := 0;
  1315. end;}
  1316. function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1317. begin
  1318. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1319. end;
  1320. function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1321. begin
  1322. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1323. end;
  1324. procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1325. begin
  1326. FOnKeyCompare := NewCompare;
  1327. if NewCompare <> nil then
  1328. OnKeyPtrCompare := @KeyCustomCompare
  1329. else
  1330. OnKeyPtrCompare := @KeyCompare;
  1331. end;
  1332. procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1333. begin
  1334. FOnDataCompare := NewCompare;
  1335. if NewCompare <> nil then
  1336. OnDataPtrCompare := @DataCustomCompare
  1337. else
  1338. OnDataPtrCompare := nil;
  1339. end;
  1340. procedure TFPGMap.InitOnPtrCompare;
  1341. begin
  1342. SetOnKeyCompare(nil);
  1343. SetOnDataCompare(nil);
  1344. end;
  1345. procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
  1346. begin
  1347. inherited PutKey(Index, @NewKey);
  1348. end;
  1349. procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
  1350. begin
  1351. inherited PutData(Index, @NewData);
  1352. end;
  1353. procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
  1354. begin
  1355. inherited PutKeyData(@AKey, @NewData);
  1356. end;
  1357. function TFPGMap.Add(const AKey: TKey): Integer;
  1358. begin
  1359. Result := inherited Add(@AKey);
  1360. end;
  1361. function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
  1362. begin
  1363. Result := inherited Add(@AKey, @AData);
  1364. end;
  1365. function TFPGMap.Find(const AKey: TKey; out Index: Integer): Boolean;
  1366. begin
  1367. Result := inherited Find(@AKey, Index);
  1368. end;
  1369. function TFPGMap.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1370. var
  1371. I: Integer;
  1372. begin
  1373. I := IndexOf(AKey);
  1374. Result := (I >= 0);
  1375. if Result then
  1376. AData := TData(inherited GetData(I)^)
  1377. else
  1378. {$IFDEF VER2_6}
  1379. FillChar(AData,SizeOf(TData),0);
  1380. {$ELSE}
  1381. AData := Default(TData);
  1382. {$ENDIF}
  1383. end;
  1384. procedure TFPGMap.AddOrSetData(const AKey: TKey; const AData: TData);
  1385. begin
  1386. inherited PutKeyData(@AKey, @AData);
  1387. end;
  1388. function TFPGMap.IndexOf(const AKey: TKey): Integer;
  1389. begin
  1390. Result := inherited IndexOf(@AKey);
  1391. end;
  1392. function TFPGMap.IndexOfData(const AData: TData): Integer;
  1393. begin
  1394. { TODO: loop ? }
  1395. Result := inherited IndexOfData(@AData);
  1396. end;
  1397. procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
  1398. begin
  1399. inherited InsertKey(Index, @AKey);
  1400. end;
  1401. procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1402. begin
  1403. inherited InsertKeyData(Index, @AKey, @AData);
  1404. end;
  1405. function TFPGMap.Remove(const AKey: TKey): Integer;
  1406. begin
  1407. Result := inherited Remove(@AKey);
  1408. end;
  1409. {****************************************************************************
  1410. TFPGMapObject
  1411. ****************************************************************************}
  1412. constructor TFPGMapObject.Create(AFreeObjects: Boolean);
  1413. begin
  1414. inherited Create(SizeOf(TKey), SizeOf(TData));
  1415. FFreeObjects := AFreeObjects;
  1416. end;
  1417. constructor TFPGMapObject.Create;
  1418. begin
  1419. Create(True);
  1420. end;
  1421. procedure TFPGMapObject.CopyItem(Src, Dest: Pointer);
  1422. begin
  1423. CopyKey(Src, Dest);
  1424. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1425. end;
  1426. procedure TFPGMapObject.CopyKey(Src, Dest: Pointer);
  1427. begin
  1428. TKey(Dest^) := TKey(Src^);
  1429. end;
  1430. procedure TFPGMapObject.CopyData(Src, Dest: Pointer);
  1431. begin
  1432. if Assigned(Pointer(Dest^)) then
  1433. TData(Dest^).Free;
  1434. TData(Dest^) := TData(Src^);
  1435. end;
  1436. procedure TFPGMapObject.Deref(Item: Pointer);
  1437. begin
  1438. Finalize(TKey(Item^));
  1439. if Assigned(PPointer(PByte(Item)+KeySize)^) and FFreeObjects then
  1440. TData(Pointer(PByte(Item)+KeySize)^).Free;
  1441. end;
  1442. function TFPGMapObject.GetKey(Index: Integer): TKey;
  1443. begin
  1444. Result := TKey(inherited GetKey(Index)^);
  1445. end;
  1446. function TFPGMapObject.GetData(Index: Integer): TData;
  1447. begin
  1448. Result := TData(inherited GetData(Index)^);
  1449. end;
  1450. function TFPGMapObject.GetKeyData(const AKey: TKey): TData;
  1451. begin
  1452. Result := TData(inherited GetKeyData(@AKey)^);
  1453. end;
  1454. function TFPGMapObject.KeyCompare(Key1, Key2: Pointer): Integer;
  1455. begin
  1456. if PKey(Key1)^ < PKey(Key2)^ then
  1457. Result := -1
  1458. else if PKey(Key1)^ > PKey(Key2)^ then
  1459. Result := 1
  1460. else
  1461. Result := 0;
  1462. end;
  1463. {function TFPGMapObject.DataCompare(Data1, Data2: Pointer): Integer;
  1464. begin
  1465. if PData(Data1)^ < PData(Data2)^ then
  1466. Result := -1
  1467. else if PData(Data1)^ > PData(Data2)^ then
  1468. Result := 1
  1469. else
  1470. Result := 0;
  1471. end;}
  1472. function TFPGMapObject.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1473. begin
  1474. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1475. end;
  1476. function TFPGMapObject.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1477. begin
  1478. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1479. end;
  1480. procedure TFPGMapObject.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1481. begin
  1482. FOnKeyCompare := NewCompare;
  1483. if NewCompare <> nil then
  1484. OnKeyPtrCompare := @KeyCustomCompare
  1485. else
  1486. OnKeyPtrCompare := @KeyCompare;
  1487. end;
  1488. procedure TFPGMapObject.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1489. begin
  1490. FOnDataCompare := NewCompare;
  1491. if NewCompare <> nil then
  1492. OnDataPtrCompare := @DataCustomCompare
  1493. else
  1494. OnDataPtrCompare := nil;
  1495. end;
  1496. procedure TFPGMapObject.InitOnPtrCompare;
  1497. begin
  1498. SetOnKeyCompare(nil);
  1499. SetOnDataCompare(nil);
  1500. end;
  1501. procedure TFPGMapObject.PutKey(Index: Integer; const NewKey: TKey);
  1502. begin
  1503. inherited PutKey(Index, @NewKey);
  1504. end;
  1505. procedure TFPGMapObject.PutData(Index: Integer; const NewData: TData);
  1506. begin
  1507. inherited PutData(Index, @NewData);
  1508. end;
  1509. procedure TFPGMapObject.PutKeyData(const AKey: TKey; const NewData: TData);
  1510. begin
  1511. inherited PutKeyData(@AKey, @NewData);
  1512. end;
  1513. function TFPGMapObject.Add(const AKey: TKey): Integer;
  1514. begin
  1515. Result := inherited Add(@AKey);
  1516. end;
  1517. function TFPGMapObject.Add(const AKey: TKey; const AData: TData): Integer;
  1518. begin
  1519. Result := inherited Add(@AKey, @AData);
  1520. end;
  1521. function TFPGMapObject.Find(const AKey: TKey; out Index: Integer): Boolean;
  1522. begin
  1523. Result := inherited Find(@AKey, Index);
  1524. end;
  1525. function TFPGMapObject.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1526. var
  1527. I: Integer;
  1528. begin
  1529. I := IndexOf(AKey);
  1530. Result := (I >= 0);
  1531. if Result then
  1532. AData := TData(inherited GetData(I)^)
  1533. else
  1534. {$IFDEF VER2_6}
  1535. FillChar(AData,SizeOf(TData),0);
  1536. {$ELSE}
  1537. AData := Default(TData);
  1538. {$ENDIF}
  1539. end;
  1540. procedure TFPGMapObject.AddOrSetData(const AKey: TKey; const AData: TData);
  1541. begin
  1542. inherited PutKeyData(@AKey, @AData);
  1543. end;
  1544. function TFPGMapObject.IndexOf(const AKey: TKey): Integer;
  1545. begin
  1546. Result := inherited IndexOf(@AKey);
  1547. end;
  1548. function TFPGMapObject.IndexOfData(const AData: TData): Integer;
  1549. begin
  1550. { TODO: loop ? }
  1551. Result := inherited IndexOfData(@AData);
  1552. end;
  1553. procedure TFPGMapObject.InsertKey(Index: Integer; const AKey: TKey);
  1554. begin
  1555. inherited InsertKey(Index, @AKey);
  1556. end;
  1557. procedure TFPGMapObject.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1558. begin
  1559. inherited InsertKeyData(Index, @AKey, @AData);
  1560. end;
  1561. function TFPGMapObject.Remove(const AKey: TKey): Integer;
  1562. begin
  1563. Result := inherited Remove(@AKey);
  1564. end;
  1565. {****************************************************************************
  1566. TFPGMapInterfacedObjectData
  1567. ****************************************************************************}
  1568. constructor TFPGMapInterfacedObjectData.Create;
  1569. begin
  1570. inherited Create(SizeOf(TKey), SizeOf(TData));
  1571. end;
  1572. procedure TFPGMapInterfacedObjectData.CopyItem(Src, Dest: Pointer);
  1573. begin
  1574. CopyKey(Src, Dest);
  1575. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1576. end;
  1577. procedure TFPGMapInterfacedObjectData.CopyKey(Src, Dest: Pointer);
  1578. begin
  1579. TKey(Dest^) := TKey(Src^);
  1580. end;
  1581. procedure TFPGMapInterfacedObjectData.CopyData(Src, Dest: Pointer);
  1582. begin
  1583. if Assigned(Pointer(Dest^)) then
  1584. TData(Dest^)._Release;
  1585. TData(Dest^) := TData(Src^);
  1586. if Assigned(Pointer(Dest^)) then
  1587. TData(Dest^)._AddRef;
  1588. end;
  1589. procedure TFPGMapInterfacedObjectData.Deref(Item: Pointer);
  1590. begin
  1591. Finalize(TKey(Item^));
  1592. if Assigned(PPointer(PByte(Item)+KeySize)^) then
  1593. TData(Pointer(PByte(Item)+KeySize)^)._Release;
  1594. end;
  1595. function TFPGMapInterfacedObjectData.GetKey(Index: Integer): TKey;
  1596. begin
  1597. Result := TKey(inherited GetKey(Index)^);
  1598. end;
  1599. function TFPGMapInterfacedObjectData.GetData(Index: Integer): TData;
  1600. begin
  1601. Result := TData(inherited GetData(Index)^);
  1602. end;
  1603. function TFPGMapInterfacedObjectData.GetKeyData(const AKey: TKey): TData;
  1604. begin
  1605. Result := TData(inherited GetKeyData(@AKey)^);
  1606. end;
  1607. function TFPGMapInterfacedObjectData.KeyCompare(Key1, Key2: Pointer): Integer;
  1608. begin
  1609. if PKey(Key1)^ < PKey(Key2)^ then
  1610. Result := -1
  1611. else if PKey(Key1)^ > PKey(Key2)^ then
  1612. Result := 1
  1613. else
  1614. Result := 0;
  1615. end;
  1616. {function TFPGMapInterfacedObjectData.DataCompare(Data1, Data2: Pointer): Integer;
  1617. begin
  1618. if PData(Data1)^ < PData(Data2)^ then
  1619. Result := -1
  1620. else if PData(Data1)^ > PData(Data2)^ then
  1621. Result := 1
  1622. else
  1623. Result := 0;
  1624. end;}
  1625. function TFPGMapInterfacedObjectData.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1626. begin
  1627. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1628. end;
  1629. function TFPGMapInterfacedObjectData.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1630. begin
  1631. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1632. end;
  1633. procedure TFPGMapInterfacedObjectData.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1634. begin
  1635. FOnKeyCompare := NewCompare;
  1636. if NewCompare <> nil then
  1637. OnKeyPtrCompare := @KeyCustomCompare
  1638. else
  1639. OnKeyPtrCompare := @KeyCompare;
  1640. end;
  1641. procedure TFPGMapInterfacedObjectData.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1642. begin
  1643. FOnDataCompare := NewCompare;
  1644. if NewCompare <> nil then
  1645. OnDataPtrCompare := @DataCustomCompare
  1646. else
  1647. OnDataPtrCompare := nil;
  1648. end;
  1649. procedure TFPGMapInterfacedObjectData.InitOnPtrCompare;
  1650. begin
  1651. SetOnKeyCompare(nil);
  1652. SetOnDataCompare(nil);
  1653. end;
  1654. procedure TFPGMapInterfacedObjectData.PutKey(Index: Integer; const NewKey: TKey);
  1655. begin
  1656. inherited PutKey(Index, @NewKey);
  1657. end;
  1658. procedure TFPGMapInterfacedObjectData.PutData(Index: Integer; const NewData: TData);
  1659. begin
  1660. inherited PutData(Index, @NewData);
  1661. end;
  1662. procedure TFPGMapInterfacedObjectData.PutKeyData(const AKey: TKey; const NewData: TData);
  1663. begin
  1664. inherited PutKeyData(@AKey, @NewData);
  1665. end;
  1666. function TFPGMapInterfacedObjectData.Add(const AKey: TKey): Integer;
  1667. begin
  1668. Result := inherited Add(@AKey);
  1669. end;
  1670. function TFPGMapInterfacedObjectData.Add(const AKey: TKey; const AData: TData): Integer;
  1671. begin
  1672. Result := inherited Add(@AKey, @AData);
  1673. end;
  1674. function TFPGMapInterfacedObjectData.Find(const AKey: TKey; out Index: Integer): Boolean;
  1675. begin
  1676. Result := inherited Find(@AKey, Index);
  1677. end;
  1678. function TFPGMapInterfacedObjectData.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1679. var
  1680. I: Integer;
  1681. begin
  1682. I := IndexOf(AKey);
  1683. Result := (I >= 0);
  1684. if Result then
  1685. AData := TData(inherited GetData(I)^)
  1686. else
  1687. {$IFDEF VER2_6}
  1688. FillChar(AData,SizeOf(TData),0);
  1689. {$ELSE}
  1690. AData := Default(TData);
  1691. {$ENDIF}
  1692. end;
  1693. procedure TFPGMapInterfacedObjectData.AddOrSetData(const AKey: TKey;
  1694. const AData: TData);
  1695. begin
  1696. inherited PutKeyData(@AKey, @AData);
  1697. end;
  1698. function TFPGMapInterfacedObjectData.IndexOf(const AKey: TKey): Integer;
  1699. begin
  1700. Result := inherited IndexOf(@AKey);
  1701. end;
  1702. function TFPGMapInterfacedObjectData.IndexOfData(const AData: TData): Integer;
  1703. begin
  1704. { TODO: loop ? }
  1705. Result := inherited IndexOfData(@AData);
  1706. end;
  1707. procedure TFPGMapInterfacedObjectData.InsertKey(Index: Integer; const AKey: TKey);
  1708. begin
  1709. inherited InsertKey(Index, @AKey);
  1710. end;
  1711. procedure TFPGMapInterfacedObjectData.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1712. begin
  1713. inherited InsertKeyData(Index, @AKey, @AData);
  1714. end;
  1715. function TFPGMapInterfacedObjectData.Remove(const AKey: TKey): Integer;
  1716. begin
  1717. Result := inherited Remove(@AKey);
  1718. end;
  1719. end.