fgl.pp 58 KB

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