fgl.pp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950
  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. Result := T(inherited GetFirst^);
  803. end;
  804. procedure TFPGList.SetFirst(const Value: T);
  805. begin
  806. inherited SetFirst(@Value);
  807. end;
  808. function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
  809. begin
  810. Result := TFPGListEnumeratorSpec.Create(Self);
  811. end;
  812. function TFPGList.IndexOf(const Item: T): Integer;
  813. begin
  814. Result := 0;
  815. {$info TODO: fix inlining to work! InternalItems[Result]^}
  816. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  817. Inc(Result);
  818. if Result = FCount then
  819. Result := -1;
  820. end;
  821. procedure TFPGList.Insert(Index: Integer; const Item: T);
  822. begin
  823. T(inherited Insert(Index)^) := Item;
  824. end;
  825. function TFPGList.GetLast: T;
  826. begin
  827. Result := T(inherited GetLast^);
  828. end;
  829. procedure TFPGList.SetLast(const Value: T);
  830. begin
  831. inherited SetLast(@Value);
  832. end;
  833. {$ifndef VER2_4}
  834. procedure TFPGList.Assign(Source: TFPGList);
  835. var
  836. i: Integer;
  837. begin
  838. Clear;
  839. for I := 0 to Source.Count - 1 do
  840. Add(Source[i]);
  841. end;
  842. {$endif VER2_4}
  843. function TFPGList.Remove(const Item: T): Integer;
  844. begin
  845. Result := IndexOf(Item);
  846. if Result >= 0 then
  847. Delete(Result);
  848. end;
  849. procedure TFPGList.Sort(Compare: TCompareFunc);
  850. begin
  851. FOnCompare := Compare;
  852. inherited Sort(@ItemPtrCompare);
  853. end;
  854. {****************************************************************************}
  855. {* TFPGObjectList *}
  856. {****************************************************************************}
  857. constructor TFPGObjectList.Create(FreeObjects: Boolean);
  858. begin
  859. inherited Create;
  860. FFreeObjects := FreeObjects;
  861. end;
  862. procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
  863. begin
  864. T(Dest^) := T(Src^);
  865. end;
  866. procedure TFPGObjectList.Deref(Item: Pointer);
  867. begin
  868. if FFreeObjects then
  869. T(Item^).Free;
  870. end;
  871. function TFPGObjectList.Get(Index: Integer): T;
  872. begin
  873. Result := T(inherited Get(Index)^);
  874. end;
  875. function TFPGObjectList.GetList: PTypeList;
  876. begin
  877. Result := PTypeList(FList);
  878. end;
  879. function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  880. begin
  881. Result := FOnCompare(T(Item1^), T(Item2^));
  882. end;
  883. procedure TFPGObjectList.Put(Index: Integer; const Item: T);
  884. begin
  885. inherited Put(Index, @Item);
  886. end;
  887. function TFPGObjectList.Add(const Item: T): Integer;
  888. begin
  889. Result := inherited Add(@Item);
  890. end;
  891. function TFPGObjectList.Extract(const Item: T): T;
  892. begin
  893. inherited Extract(@Item, @Result);
  894. end;
  895. function TFPGObjectList.GetFirst: T;
  896. begin
  897. Result := T(inherited GetFirst^);
  898. end;
  899. procedure TFPGObjectList.SetFirst(const Value: T);
  900. begin
  901. inherited SetFirst(@Value);
  902. end;
  903. function TFPGObjectList.GetEnumerator: TFPGListEnumeratorSpec;
  904. begin
  905. Result := TFPGListEnumeratorSpec.Create(Self);
  906. end;
  907. function TFPGObjectList.IndexOf(const Item: T): Integer;
  908. begin
  909. Result := 0;
  910. {$info TODO: fix inlining to work! InternalItems[Result]^}
  911. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  912. Inc(Result);
  913. if Result = FCount then
  914. Result := -1;
  915. end;
  916. procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
  917. begin
  918. T(inherited Insert(Index)^) := Item;
  919. end;
  920. function TFPGObjectList.GetLast: T;
  921. begin
  922. Result := T(inherited GetLast^);
  923. end;
  924. procedure TFPGObjectList.SetLast(const Value: T);
  925. begin
  926. inherited SetLast(@Value);
  927. end;
  928. {$ifndef VER2_4}
  929. procedure TFPGObjectList.Assign(Source: TFPGObjectList);
  930. var
  931. i: Integer;
  932. begin
  933. Clear;
  934. for I := 0 to Source.Count - 1 do
  935. Add(Source[i]);
  936. end;
  937. {$endif VER2_4}
  938. function TFPGObjectList.Remove(const Item: T): Integer;
  939. begin
  940. Result := IndexOf(Item);
  941. if Result >= 0 then
  942. Delete(Result);
  943. end;
  944. procedure TFPGObjectList.Sort(Compare: TCompareFunc);
  945. begin
  946. FOnCompare := Compare;
  947. inherited Sort(@ItemPtrCompare);
  948. end;
  949. {****************************************************************************}
  950. {* TFPGInterfacedObjectList *}
  951. {****************************************************************************}
  952. constructor TFPGInterfacedObjectList.Create;
  953. begin
  954. inherited Create;
  955. end;
  956. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  957. begin
  958. if Assigned(Pointer(Dest^)) then
  959. T(Dest^)._Release;
  960. Pointer(Dest^) := Pointer(Src^);
  961. if Assigned(Pointer(Dest^)) then
  962. T(Dest^)._AddRef;
  963. end;
  964. procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
  965. begin
  966. if Assigned(Pointer(Item^)) then
  967. T(Item^)._Release;
  968. end;
  969. function TFPGInterfacedObjectList.Get(Index: Integer): T;
  970. begin
  971. Result := T(inherited Get(Index)^);
  972. end;
  973. function TFPGInterfacedObjectList.GetList: PTypeList;
  974. begin
  975. Result := PTypeList(FList);
  976. end;
  977. function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
  978. begin
  979. Result := FOnCompare(T(Item1^), T(Item2^));
  980. end;
  981. procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
  982. begin
  983. inherited Put(Index, @Item);
  984. end;
  985. function TFPGInterfacedObjectList.Add(const Item: T): Integer;
  986. begin
  987. Result := inherited Add(@Item);
  988. end;
  989. function TFPGInterfacedObjectList.Extract(const Item: T): T;
  990. begin
  991. inherited Extract(@Item, @Result);
  992. end;
  993. function TFPGInterfacedObjectList.GetFirst: T;
  994. begin
  995. Result := T(inherited GetFirst^);
  996. end;
  997. procedure TFPGInterfacedObjectList.SetFirst(const Value: T);
  998. begin
  999. inherited SetFirst(@Value);
  1000. end;
  1001. function TFPGInterfacedObjectList.GetEnumerator: TFPGListEnumeratorSpec;
  1002. begin
  1003. Result := TFPGListEnumeratorSpec.Create(Self);
  1004. end;
  1005. function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
  1006. begin
  1007. Result := 0;
  1008. {$info TODO: fix inlining to work! InternalItems[Result]^}
  1009. while (Result < FCount) and (PT(FList)[Result] <> Item) do
  1010. Inc(Result);
  1011. if Result = FCount then
  1012. Result := -1;
  1013. end;
  1014. procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
  1015. begin
  1016. T(inherited Insert(Index)^) := Item;
  1017. end;
  1018. function TFPGInterfacedObjectList.GetLast: T;
  1019. begin
  1020. Result := T(inherited GetLast^);
  1021. end;
  1022. procedure TFPGInterfacedObjectList.SetLast(const Value: T);
  1023. begin
  1024. inherited SetLast(@Value);
  1025. end;
  1026. {$ifndef VER2_4}
  1027. procedure TFPGInterfacedObjectList.Assign(Source: TFPGInterfacedObjectList);
  1028. var
  1029. i: Integer;
  1030. begin
  1031. Clear;
  1032. for I := 0 to Source.Count - 1 do
  1033. Add(Source[i]);
  1034. end;
  1035. {$endif VER2_4}
  1036. function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
  1037. begin
  1038. Result := IndexOf(Item);
  1039. if Result >= 0 then
  1040. Delete(Result);
  1041. end;
  1042. procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
  1043. begin
  1044. FOnCompare := Compare;
  1045. inherited Sort(@ItemPtrCompare);
  1046. end;
  1047. {****************************************************************************
  1048. TFPSMap
  1049. ****************************************************************************}
  1050. constructor TFPSMap.Create(AKeySize: Integer; ADataSize: integer);
  1051. begin
  1052. inherited Create(AKeySize+ADataSize);
  1053. FKeySize := AKeySize;
  1054. FDataSize := ADataSize;
  1055. InitOnPtrCompare;
  1056. end;
  1057. procedure TFPSMap.CopyKey(Src, Dest: Pointer);
  1058. begin
  1059. System.Move(Src^, Dest^, FKeySize);
  1060. end;
  1061. procedure TFPSMap.CopyData(Src, Dest: Pointer);
  1062. begin
  1063. System.Move(Src^, Dest^, FDataSize);
  1064. end;
  1065. function TFPSMap.GetKey(Index: Integer): Pointer;
  1066. begin
  1067. Result := Items[Index];
  1068. end;
  1069. function TFPSMap.GetData(Index: Integer): Pointer;
  1070. begin
  1071. Result := PByte(Items[Index])+FKeySize;
  1072. end;
  1073. function TFPSMap.GetKeyData(AKey: Pointer): Pointer;
  1074. var
  1075. I: Integer;
  1076. begin
  1077. I := IndexOf(AKey);
  1078. if I >= 0 then
  1079. Result := InternalItems[I]+FKeySize
  1080. else
  1081. Error(SMapKeyError, PtrUInt(AKey));
  1082. end;
  1083. function TFPSMap.BinaryCompareKey(Key1, Key2: Pointer): Integer;
  1084. begin
  1085. Result := CompareByte(Key1^, Key2^, FKeySize);
  1086. end;
  1087. function TFPSMap.BinaryCompareData(Data1, Data2: Pointer): Integer;
  1088. begin
  1089. Result := CompareByte(Data1^, Data2^, FDataSize);
  1090. end;
  1091. procedure TFPSMap.SetOnKeyPtrCompare(Proc: TFPSListCompareFunc);
  1092. begin
  1093. if Proc <> nil then
  1094. FOnKeyPtrCompare := Proc
  1095. else
  1096. FOnKeyPtrCompare := @BinaryCompareKey;
  1097. end;
  1098. procedure TFPSMap.SetOnDataPtrCompare(Proc: TFPSListCompareFunc);
  1099. begin
  1100. if Proc <> nil then
  1101. FOnDataPtrCompare := Proc
  1102. else
  1103. FOnDataPtrCompare := @BinaryCompareData;
  1104. end;
  1105. procedure TFPSMap.InitOnPtrCompare;
  1106. begin
  1107. SetOnKeyPtrCompare(nil);
  1108. SetOnDataPtrCompare(nil);
  1109. end;
  1110. procedure TFPSMap.PutKey(Index: Integer; AKey: Pointer);
  1111. begin
  1112. if FSorted then
  1113. Error(SSortedListError, 0);
  1114. CopyKey(AKey, Items[Index]);
  1115. end;
  1116. procedure TFPSMap.PutData(Index: Integer; AData: Pointer);
  1117. begin
  1118. CopyData(AData, PByte(Items[Index])+FKeySize);
  1119. end;
  1120. procedure TFPSMap.PutKeyData(AKey: Pointer; NewData: Pointer);
  1121. var
  1122. I: Integer;
  1123. begin
  1124. I := IndexOf(AKey);
  1125. if I >= 0 then
  1126. Data[I] := NewData
  1127. else
  1128. Add(AKey, NewData);
  1129. end;
  1130. procedure TFPSMap.SetSorted(Value: Boolean);
  1131. begin
  1132. if Value = FSorted then exit;
  1133. FSorted := Value;
  1134. if Value then Sort;
  1135. end;
  1136. function TFPSMap.Add(AKey: Pointer): Integer;
  1137. begin
  1138. if Sorted then
  1139. begin
  1140. if Find(AKey, Result) then
  1141. case Duplicates of
  1142. dupIgnore: exit;
  1143. dupError: Error(SDuplicateItem, 0)
  1144. end;
  1145. end else
  1146. Result := Count;
  1147. CopyKey(AKey, inherited Insert(Result));
  1148. end;
  1149. function TFPSMap.Add(AKey, AData: Pointer): Integer;
  1150. begin
  1151. Result := Add(AKey);
  1152. Data[Result] := AData;
  1153. end;
  1154. function TFPSMap.Find(AKey: Pointer; out Index: Integer): Boolean;
  1155. { Searches for the first item <= Key, returns True if exact match,
  1156. sets index to the index of the found string. }
  1157. var
  1158. I,L,R,Dir: Integer;
  1159. begin
  1160. Result := false;
  1161. // Use binary search.
  1162. L := 0;
  1163. R := FCount-1;
  1164. while L<=R do
  1165. begin
  1166. I := L + (R - L) div 2;
  1167. Dir := FOnKeyPtrCompare(Items[I], AKey);
  1168. if Dir < 0 then
  1169. L := I+1
  1170. else begin
  1171. R := I-1;
  1172. if Dir = 0 then
  1173. begin
  1174. Result := true;
  1175. if Duplicates <> dupAccept then
  1176. L := I;
  1177. end;
  1178. end;
  1179. end;
  1180. Index := L;
  1181. end;
  1182. function TFPSMap.LinearIndexOf(AKey: Pointer): Integer;
  1183. var
  1184. ListItem: Pointer;
  1185. begin
  1186. Result := 0;
  1187. ListItem := First;
  1188. while (Result < FCount) and (FOnKeyPtrCompare(ListItem, AKey) <> 0) do
  1189. begin
  1190. Inc(Result);
  1191. ListItem := PByte(ListItem)+FItemSize;
  1192. end;
  1193. if Result = FCount then Result := -1;
  1194. end;
  1195. function TFPSMap.IndexOf(AKey: Pointer): Integer;
  1196. begin
  1197. if Sorted then
  1198. begin
  1199. if not Find(AKey, Result) then
  1200. Result := -1;
  1201. end else
  1202. Result := LinearIndexOf(AKey);
  1203. end;
  1204. function TFPSMap.IndexOfData(AData: Pointer): Integer;
  1205. var
  1206. ListItem: Pointer;
  1207. begin
  1208. Result := 0;
  1209. ListItem := First+FKeySize;
  1210. while (Result < FCount) and (FOnDataPtrCompare(ListItem, AData) <> 0) do
  1211. begin
  1212. Inc(Result);
  1213. ListItem := PByte(ListItem)+FItemSize;
  1214. end;
  1215. if Result = FCount then Result := -1;
  1216. end;
  1217. function TFPSMap.Insert(Index: Integer): Pointer;
  1218. begin
  1219. if FSorted then
  1220. Error(SSortedListError, 0);
  1221. Result := inherited Insert(Index);
  1222. end;
  1223. procedure TFPSMap.Insert(Index: Integer; out AKey, AData: Pointer);
  1224. begin
  1225. AKey := Insert(Index);
  1226. AData := PByte(AKey) + FKeySize;
  1227. end;
  1228. procedure TFPSMap.InsertKey(Index: Integer; AKey: Pointer);
  1229. begin
  1230. CopyKey(AKey, Insert(Index));
  1231. end;
  1232. procedure TFPSMap.InsertKeyData(Index: Integer; AKey, AData: Pointer);
  1233. var
  1234. ListItem: Pointer;
  1235. begin
  1236. ListItem := Insert(Index);
  1237. CopyKey(AKey, ListItem);
  1238. CopyData(AData, PByte(ListItem)+FKeySize);
  1239. end;
  1240. function TFPSMap.Remove(AKey: Pointer): Integer;
  1241. begin
  1242. Result := IndexOf(AKey);
  1243. if Result >= 0 then
  1244. Delete(Result);
  1245. end;
  1246. procedure TFPSMap.Sort;
  1247. begin
  1248. inherited Sort(FOnKeyPtrCompare);
  1249. end;
  1250. {****************************************************************************
  1251. TFPGMap
  1252. ****************************************************************************}
  1253. constructor TFPGMap.Create;
  1254. begin
  1255. inherited Create(SizeOf(TKey), SizeOf(TData));
  1256. end;
  1257. procedure TFPGMap.CopyItem(Src, Dest: Pointer);
  1258. begin
  1259. CopyKey(Src, Dest);
  1260. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1261. end;
  1262. procedure TFPGMap.CopyKey(Src, Dest: Pointer);
  1263. begin
  1264. TKey(Dest^) := TKey(Src^);
  1265. end;
  1266. procedure TFPGMap.CopyData(Src, Dest: Pointer);
  1267. begin
  1268. TData(Dest^) := TData(Src^);
  1269. end;
  1270. procedure TFPGMap.Deref(Item: Pointer);
  1271. begin
  1272. Finalize(TKey(Item^));
  1273. Finalize(TData(Pointer(PByte(Item)+KeySize)^));
  1274. end;
  1275. function TFPGMap.GetKey(Index: Integer): TKey;
  1276. begin
  1277. Result := TKey(inherited GetKey(Index)^);
  1278. end;
  1279. function TFPGMap.GetData(Index: Integer): TData;
  1280. begin
  1281. Result := TData(inherited GetData(Index)^);
  1282. end;
  1283. function TFPGMap.GetKeyData(const AKey: TKey): TData;
  1284. begin
  1285. Result := TData(inherited GetKeyData(@AKey)^);
  1286. end;
  1287. function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
  1288. begin
  1289. if PKey(Key1)^ < PKey(Key2)^ then
  1290. Result := -1
  1291. else if PKey(Key1)^ > PKey(Key2)^ then
  1292. Result := 1
  1293. else
  1294. Result := 0;
  1295. end;
  1296. {function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
  1297. begin
  1298. if PData(Data1)^ < PData(Data2)^ then
  1299. Result := -1
  1300. else if PData(Data1)^ > PData(Data2)^ then
  1301. Result := 1
  1302. else
  1303. Result := 0;
  1304. end;}
  1305. function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1306. begin
  1307. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1308. end;
  1309. function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1310. begin
  1311. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1312. end;
  1313. procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1314. begin
  1315. FOnKeyCompare := NewCompare;
  1316. if NewCompare <> nil then
  1317. OnKeyPtrCompare := @KeyCustomCompare
  1318. else
  1319. OnKeyPtrCompare := @KeyCompare;
  1320. end;
  1321. procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1322. begin
  1323. FOnDataCompare := NewCompare;
  1324. if NewCompare <> nil then
  1325. OnDataPtrCompare := @DataCustomCompare
  1326. else
  1327. OnDataPtrCompare := nil;
  1328. end;
  1329. procedure TFPGMap.InitOnPtrCompare;
  1330. begin
  1331. SetOnKeyCompare(nil);
  1332. SetOnDataCompare(nil);
  1333. end;
  1334. procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
  1335. begin
  1336. inherited PutKey(Index, @NewKey);
  1337. end;
  1338. procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
  1339. begin
  1340. inherited PutData(Index, @NewData);
  1341. end;
  1342. procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
  1343. begin
  1344. inherited PutKeyData(@AKey, @NewData);
  1345. end;
  1346. function TFPGMap.Add(const AKey: TKey): Integer;
  1347. begin
  1348. Result := inherited Add(@AKey);
  1349. end;
  1350. function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
  1351. begin
  1352. Result := inherited Add(@AKey, @AData);
  1353. end;
  1354. function TFPGMap.Find(const AKey: TKey; out Index: Integer): Boolean;
  1355. begin
  1356. Result := inherited Find(@AKey, Index);
  1357. end;
  1358. function TFPGMap.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1359. var
  1360. I: Integer;
  1361. begin
  1362. Result := inherited Find(@AKey, I);
  1363. if Result then
  1364. AData := TData(inherited GetData(I)^)
  1365. else
  1366. {$IFDEF VER2_6}
  1367. FillChar(AData,SizeOf(TData),0);
  1368. {$ELSE}
  1369. AData := Default(TData);
  1370. {$ENDIF}
  1371. end;
  1372. procedure TFPGMap.AddOrSetData(const AKey: TKey; const AData: TData);
  1373. begin
  1374. inherited PutKeyData(@AKey, @AData);
  1375. end;
  1376. function TFPGMap.IndexOf(const AKey: TKey): Integer;
  1377. begin
  1378. Result := inherited IndexOf(@AKey);
  1379. end;
  1380. function TFPGMap.IndexOfData(const AData: TData): Integer;
  1381. begin
  1382. { TODO: loop ? }
  1383. Result := inherited IndexOfData(@AData);
  1384. end;
  1385. procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
  1386. begin
  1387. inherited InsertKey(Index, @AKey);
  1388. end;
  1389. procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1390. begin
  1391. inherited InsertKeyData(Index, @AKey, @AData);
  1392. end;
  1393. function TFPGMap.Remove(const AKey: TKey): Integer;
  1394. begin
  1395. Result := inherited Remove(@AKey);
  1396. end;
  1397. {****************************************************************************
  1398. TFPGMapObject
  1399. ****************************************************************************}
  1400. constructor TFPGMapObject.Create(AFreeObjects: Boolean);
  1401. begin
  1402. inherited Create(SizeOf(TKey), SizeOf(TData));
  1403. FFreeObjects := AFreeObjects;
  1404. end;
  1405. constructor TFPGMapObject.Create;
  1406. begin
  1407. Create(True);
  1408. end;
  1409. procedure TFPGMapObject.CopyItem(Src, Dest: Pointer);
  1410. begin
  1411. CopyKey(Src, Dest);
  1412. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1413. end;
  1414. procedure TFPGMapObject.CopyKey(Src, Dest: Pointer);
  1415. begin
  1416. TKey(Dest^) := TKey(Src^);
  1417. end;
  1418. procedure TFPGMapObject.CopyData(Src, Dest: Pointer);
  1419. begin
  1420. if Assigned(Pointer(Dest^)) then
  1421. TData(Dest^).Free;
  1422. TData(Dest^) := TData(Src^);
  1423. end;
  1424. procedure TFPGMapObject.Deref(Item: Pointer);
  1425. begin
  1426. Finalize(TKey(Item^));
  1427. if Assigned(PPointer(PByte(Item)+KeySize)^) and FFreeObjects then
  1428. TData(Pointer(PByte(Item)+KeySize)^).Free;
  1429. end;
  1430. function TFPGMapObject.GetKey(Index: Integer): TKey;
  1431. begin
  1432. Result := TKey(inherited GetKey(Index)^);
  1433. end;
  1434. function TFPGMapObject.GetData(Index: Integer): TData;
  1435. begin
  1436. Result := TData(inherited GetData(Index)^);
  1437. end;
  1438. function TFPGMapObject.GetKeyData(const AKey: TKey): TData;
  1439. begin
  1440. Result := TData(inherited GetKeyData(@AKey)^);
  1441. end;
  1442. function TFPGMapObject.KeyCompare(Key1, Key2: Pointer): Integer;
  1443. begin
  1444. if PKey(Key1)^ < PKey(Key2)^ then
  1445. Result := -1
  1446. else if PKey(Key1)^ > PKey(Key2)^ then
  1447. Result := 1
  1448. else
  1449. Result := 0;
  1450. end;
  1451. {function TFPGMapObject.DataCompare(Data1, Data2: Pointer): Integer;
  1452. begin
  1453. if PData(Data1)^ < PData(Data2)^ then
  1454. Result := -1
  1455. else if PData(Data1)^ > PData(Data2)^ then
  1456. Result := 1
  1457. else
  1458. Result := 0;
  1459. end;}
  1460. function TFPGMapObject.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1461. begin
  1462. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1463. end;
  1464. function TFPGMapObject.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1465. begin
  1466. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1467. end;
  1468. procedure TFPGMapObject.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1469. begin
  1470. FOnKeyCompare := NewCompare;
  1471. if NewCompare <> nil then
  1472. OnKeyPtrCompare := @KeyCustomCompare
  1473. else
  1474. OnKeyPtrCompare := @KeyCompare;
  1475. end;
  1476. procedure TFPGMapObject.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1477. begin
  1478. FOnDataCompare := NewCompare;
  1479. if NewCompare <> nil then
  1480. OnDataPtrCompare := @DataCustomCompare
  1481. else
  1482. OnDataPtrCompare := nil;
  1483. end;
  1484. procedure TFPGMapObject.InitOnPtrCompare;
  1485. begin
  1486. SetOnKeyCompare(nil);
  1487. SetOnDataCompare(nil);
  1488. end;
  1489. procedure TFPGMapObject.PutKey(Index: Integer; const NewKey: TKey);
  1490. begin
  1491. inherited PutKey(Index, @NewKey);
  1492. end;
  1493. procedure TFPGMapObject.PutData(Index: Integer; const NewData: TData);
  1494. begin
  1495. inherited PutData(Index, @NewData);
  1496. end;
  1497. procedure TFPGMapObject.PutKeyData(const AKey: TKey; const NewData: TData);
  1498. begin
  1499. inherited PutKeyData(@AKey, @NewData);
  1500. end;
  1501. function TFPGMapObject.Add(const AKey: TKey): Integer;
  1502. begin
  1503. Result := inherited Add(@AKey);
  1504. end;
  1505. function TFPGMapObject.Add(const AKey: TKey; const AData: TData): Integer;
  1506. begin
  1507. Result := inherited Add(@AKey, @AData);
  1508. end;
  1509. function TFPGMapObject.Find(const AKey: TKey; out Index: Integer): Boolean;
  1510. begin
  1511. Result := inherited Find(@AKey, Index);
  1512. end;
  1513. function TFPGMapObject.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1514. var
  1515. I: Integer;
  1516. begin
  1517. Result := inherited Find(@AKey, I);
  1518. if Result then
  1519. AData := TData(inherited GetData(I)^)
  1520. else
  1521. {$IFDEF VER2_6}
  1522. FillChar(AData,SizeOf(TData),0);
  1523. {$ELSE}
  1524. AData := Default(TData);
  1525. {$ENDIF}
  1526. end;
  1527. procedure TFPGMapObject.AddOrSetData(const AKey: TKey; const AData: TData);
  1528. begin
  1529. inherited PutKeyData(@AKey, @AData);
  1530. end;
  1531. function TFPGMapObject.IndexOf(const AKey: TKey): Integer;
  1532. begin
  1533. Result := inherited IndexOf(@AKey);
  1534. end;
  1535. function TFPGMapObject.IndexOfData(const AData: TData): Integer;
  1536. begin
  1537. { TODO: loop ? }
  1538. Result := inherited IndexOfData(@AData);
  1539. end;
  1540. procedure TFPGMapObject.InsertKey(Index: Integer; const AKey: TKey);
  1541. begin
  1542. inherited InsertKey(Index, @AKey);
  1543. end;
  1544. procedure TFPGMapObject.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1545. begin
  1546. inherited InsertKeyData(Index, @AKey, @AData);
  1547. end;
  1548. function TFPGMapObject.Remove(const AKey: TKey): Integer;
  1549. begin
  1550. Result := inherited Remove(@AKey);
  1551. end;
  1552. {****************************************************************************
  1553. TFPGMapInterfacedObjectData
  1554. ****************************************************************************}
  1555. constructor TFPGMapInterfacedObjectData.Create;
  1556. begin
  1557. inherited Create(SizeOf(TKey), SizeOf(TData));
  1558. end;
  1559. procedure TFPGMapInterfacedObjectData.CopyItem(Src, Dest: Pointer);
  1560. begin
  1561. CopyKey(Src, Dest);
  1562. CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
  1563. end;
  1564. procedure TFPGMapInterfacedObjectData.CopyKey(Src, Dest: Pointer);
  1565. begin
  1566. TKey(Dest^) := TKey(Src^);
  1567. end;
  1568. procedure TFPGMapInterfacedObjectData.CopyData(Src, Dest: Pointer);
  1569. begin
  1570. if Assigned(Pointer(Dest^)) then
  1571. TData(Dest^)._Release;
  1572. TData(Dest^) := TData(Src^);
  1573. if Assigned(Pointer(Dest^)) then
  1574. TData(Dest^)._AddRef;
  1575. end;
  1576. procedure TFPGMapInterfacedObjectData.Deref(Item: Pointer);
  1577. begin
  1578. Finalize(TKey(Item^));
  1579. if Assigned(PPointer(PByte(Item)+KeySize)^) then
  1580. TData(Pointer(PByte(Item)+KeySize)^)._Release;
  1581. end;
  1582. function TFPGMapInterfacedObjectData.GetKey(Index: Integer): TKey;
  1583. begin
  1584. Result := TKey(inherited GetKey(Index)^);
  1585. end;
  1586. function TFPGMapInterfacedObjectData.GetData(Index: Integer): TData;
  1587. begin
  1588. Result := TData(inherited GetData(Index)^);
  1589. end;
  1590. function TFPGMapInterfacedObjectData.GetKeyData(const AKey: TKey): TData;
  1591. begin
  1592. Result := TData(inherited GetKeyData(@AKey)^);
  1593. end;
  1594. function TFPGMapInterfacedObjectData.KeyCompare(Key1, Key2: Pointer): Integer;
  1595. begin
  1596. if PKey(Key1)^ < PKey(Key2)^ then
  1597. Result := -1
  1598. else if PKey(Key1)^ > PKey(Key2)^ then
  1599. Result := 1
  1600. else
  1601. Result := 0;
  1602. end;
  1603. {function TFPGMapInterfacedObjectData.DataCompare(Data1, Data2: Pointer): Integer;
  1604. begin
  1605. if PData(Data1)^ < PData(Data2)^ then
  1606. Result := -1
  1607. else if PData(Data1)^ > PData(Data2)^ then
  1608. Result := 1
  1609. else
  1610. Result := 0;
  1611. end;}
  1612. function TFPGMapInterfacedObjectData.KeyCustomCompare(Key1, Key2: Pointer): Integer;
  1613. begin
  1614. Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
  1615. end;
  1616. function TFPGMapInterfacedObjectData.DataCustomCompare(Data1, Data2: Pointer): Integer;
  1617. begin
  1618. Result := FOnDataCompare(TData(Data1^), TData(Data2^));
  1619. end;
  1620. procedure TFPGMapInterfacedObjectData.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
  1621. begin
  1622. FOnKeyCompare := NewCompare;
  1623. if NewCompare <> nil then
  1624. OnKeyPtrCompare := @KeyCustomCompare
  1625. else
  1626. OnKeyPtrCompare := @KeyCompare;
  1627. end;
  1628. procedure TFPGMapInterfacedObjectData.SetOnDataCompare(NewCompare: TDataCompareFunc);
  1629. begin
  1630. FOnDataCompare := NewCompare;
  1631. if NewCompare <> nil then
  1632. OnDataPtrCompare := @DataCustomCompare
  1633. else
  1634. OnDataPtrCompare := nil;
  1635. end;
  1636. procedure TFPGMapInterfacedObjectData.InitOnPtrCompare;
  1637. begin
  1638. SetOnKeyCompare(nil);
  1639. SetOnDataCompare(nil);
  1640. end;
  1641. procedure TFPGMapInterfacedObjectData.PutKey(Index: Integer; const NewKey: TKey);
  1642. begin
  1643. inherited PutKey(Index, @NewKey);
  1644. end;
  1645. procedure TFPGMapInterfacedObjectData.PutData(Index: Integer; const NewData: TData);
  1646. begin
  1647. inherited PutData(Index, @NewData);
  1648. end;
  1649. procedure TFPGMapInterfacedObjectData.PutKeyData(const AKey: TKey; const NewData: TData);
  1650. begin
  1651. inherited PutKeyData(@AKey, @NewData);
  1652. end;
  1653. function TFPGMapInterfacedObjectData.Add(const AKey: TKey): Integer;
  1654. begin
  1655. Result := inherited Add(@AKey);
  1656. end;
  1657. function TFPGMapInterfacedObjectData.Add(const AKey: TKey; const AData: TData): Integer;
  1658. begin
  1659. Result := inherited Add(@AKey, @AData);
  1660. end;
  1661. function TFPGMapInterfacedObjectData.Find(const AKey: TKey; out Index: Integer): Boolean;
  1662. begin
  1663. Result := inherited Find(@AKey, Index);
  1664. end;
  1665. function TFPGMapInterfacedObjectData.TryGetData(const AKey: TKey; out AData: TData): Boolean;
  1666. var
  1667. I: Integer;
  1668. begin
  1669. Result := inherited Find(@AKey, I);
  1670. if Result then
  1671. AData := TData(inherited GetData(I)^)
  1672. else
  1673. {$IFDEF VER2_6}
  1674. FillChar(AData,SizeOf(TData),0);
  1675. {$ELSE}
  1676. AData := Default(TData);
  1677. {$ENDIF}
  1678. end;
  1679. procedure TFPGMapInterfacedObjectData.AddOrSetData(const AKey: TKey;
  1680. const AData: TData);
  1681. begin
  1682. inherited PutKeyData(@AKey, @AData);
  1683. end;
  1684. function TFPGMapInterfacedObjectData.IndexOf(const AKey: TKey): Integer;
  1685. begin
  1686. Result := inherited IndexOf(@AKey);
  1687. end;
  1688. function TFPGMapInterfacedObjectData.IndexOfData(const AData: TData): Integer;
  1689. begin
  1690. { TODO: loop ? }
  1691. Result := inherited IndexOfData(@AData);
  1692. end;
  1693. procedure TFPGMapInterfacedObjectData.InsertKey(Index: Integer; const AKey: TKey);
  1694. begin
  1695. inherited InsertKey(Index, @AKey);
  1696. end;
  1697. procedure TFPGMapInterfacedObjectData.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
  1698. begin
  1699. inherited InsertKeyData(Index, @AKey, @AData);
  1700. end;
  1701. function TFPGMapInterfacedObjectData.Remove(const AKey: TKey): Integer;
  1702. begin
  1703. Result := inherited Remove(@AKey);
  1704. end;
  1705. end.