fgl.pp 59 KB

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