fgl.pp 55 KB

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