cclasses.pas 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  3. This module provides some basic classes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  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. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit cclasses;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. SysUtils,
  22. CUtils,CStreams;
  23. {********************************************
  24. TMemDebug
  25. ********************************************}
  26. type
  27. tmemdebug = class
  28. private
  29. totalmem,
  30. startmem : integer;
  31. infostr : string[40];
  32. public
  33. constructor Create(const s:string);
  34. destructor Destroy;override;
  35. procedure show;
  36. procedure start;
  37. procedure stop;
  38. end;
  39. {*******************************************************
  40. TFPList (From rtl/objpas/classes/classesh.inc)
  41. ********************************************************}
  42. const
  43. SListIndexError = 'List index exceeds bounds (%d)';
  44. SListCapacityError = 'The maximum list capacity is reached (%d)';
  45. SListCountError = 'List count too large (%d)';
  46. type
  47. EListError = class(Exception);
  48. const
  49. MaxListSize = Maxint div 16;
  50. type
  51. PPointerList = ^TPointerList;
  52. TPointerList = array[0..MaxListSize - 1] of Pointer;
  53. TListSortCompare = function (Item1, Item2: Pointer): Integer;
  54. TListCallback = procedure(data,arg:pointer) of object;
  55. TListStaticCallback = procedure(data,arg:pointer);
  56. TFPList = class(TObject)
  57. private
  58. FList: PPointerList;
  59. FCount: Integer;
  60. FCapacity: Integer;
  61. protected
  62. function Get(Index: Integer): Pointer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  63. procedure Put(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  64. procedure SetCapacity(NewCapacity: Integer);
  65. procedure SetCount(NewCount: Integer);
  66. Procedure RaiseIndexError(Index : Integer);
  67. public
  68. destructor Destroy; override;
  69. function Add(Item: Pointer): Integer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  70. procedure Clear;
  71. procedure Delete(Index: Integer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  72. class procedure Error(const Msg: string; Data: PtrInt);
  73. procedure Exchange(Index1, Index2: Integer);
  74. function Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  75. function Extract(item: Pointer): Pointer;
  76. function First: Pointer;
  77. function IndexOf(Item: Pointer): Integer;
  78. procedure Insert(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  79. function Last: Pointer;
  80. procedure Move(CurIndex, NewIndex: Integer);
  81. procedure Assign(Obj:TFPList);
  82. function Remove(Item: Pointer): Integer;
  83. procedure Pack;
  84. procedure Sort(Compare: TListSortCompare);
  85. procedure ForEachCall(proc2call:TListCallback;arg:pointer);
  86. procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  87. property Capacity: Integer read FCapacity write SetCapacity;
  88. property Count: Integer read FCount write SetCount;
  89. property Items[Index: Integer]: Pointer read Get write Put; default;
  90. property List: PPointerList read FList;
  91. end;
  92. {*******************************************************
  93. TFPObjectList (From fcl/inc/contnrs.pp)
  94. ********************************************************}
  95. TObjectListCallback = procedure(data:TObject;arg:pointer) of object;
  96. TObjectListStaticCallback = procedure(data:TObject;arg:pointer);
  97. TFPObjectList = class(TObject)
  98. private
  99. FFreeObjects : Boolean;
  100. FList: TFPList;
  101. function GetCount: integer;
  102. procedure SetCount(const AValue: integer);
  103. protected
  104. function GetItem(Index: Integer): TObject; {$ifdef CLASSESINLINE}inline;{$endif}
  105. procedure SetItem(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  106. procedure SetCapacity(NewCapacity: Integer);
  107. function GetCapacity: integer;
  108. public
  109. constructor Create;
  110. constructor Create(FreeObjects : Boolean);
  111. destructor Destroy; override;
  112. procedure Clear;
  113. function Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
  114. procedure Delete(Index: Integer); {$ifdef CLASSESINLINE}inline;{$endif}
  115. procedure Exchange(Index1, Index2: Integer);
  116. function Expand: TFPObjectList;
  117. function Extract(Item: TObject): TObject;
  118. function Remove(AObject: TObject): Integer;
  119. function IndexOf(AObject: TObject): Integer;
  120. function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  121. procedure Insert(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  122. function First: TObject;
  123. function Last: TObject;
  124. procedure Move(CurIndex, NewIndex: Integer);
  125. procedure Assign(Obj:TFPObjectList);
  126. procedure Pack;
  127. procedure Sort(Compare: TListSortCompare);
  128. procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  129. procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  130. property Capacity: Integer read GetCapacity write SetCapacity;
  131. property Count: Integer read GetCount write SetCount;
  132. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  133. property Items[Index: Integer]: TObject read GetItem write SetItem; default;
  134. property List: TFPList read FList;
  135. end;
  136. type
  137. THashItem=record
  138. HashValue : LongWord;
  139. StrIndex : Integer;
  140. NextIndex : Integer;
  141. Data : Pointer;
  142. end;
  143. PHashItem=^THashItem;
  144. const
  145. MaxHashListSize = Maxint div 16;
  146. MaxHashStrSize = Maxint;
  147. MaxHashTableSize = Maxint div 4;
  148. MaxItemsPerHash = 3;
  149. type
  150. PHashItemList = ^THashItemList;
  151. THashItemList = array[0..MaxHashListSize - 1] of THashItem;
  152. PHashTable = ^THashTable;
  153. THashTable = array[0..MaxHashTableSize - 1] of Integer;
  154. TFPHashList = class(TObject)
  155. private
  156. { ItemList }
  157. FHashList : PHashItemList;
  158. FCount,
  159. FCapacity : Integer;
  160. { Hash }
  161. FHashTable : PHashTable;
  162. FHashCapacity : Integer;
  163. { Strings }
  164. FStrs : PChar;
  165. FStrCount,
  166. FStrCapacity : Integer;
  167. protected
  168. function Get(Index: Integer): Pointer;
  169. procedure SetCapacity(NewCapacity: Integer);
  170. procedure SetCount(NewCount: Integer);
  171. Procedure RaiseIndexError(Index : Integer);
  172. function AddStr(const s:string): Integer;
  173. procedure AddToHashTable(Index: Integer);
  174. procedure StrExpand(MinIncSize:Integer);
  175. procedure SetStrCapacity(NewCapacity: Integer);
  176. procedure SetHashCapacity(NewCapacity: Integer);
  177. procedure ReHash;
  178. public
  179. constructor Create;
  180. destructor Destroy; override;
  181. function Add(const AName:string;Item: Pointer): Integer;
  182. procedure Clear;
  183. function NameOfIndex(Index: Integer): String;
  184. procedure Delete(Index: Integer);
  185. class procedure Error(const Msg: string; Data: PtrInt);
  186. function Expand: TFPHashList;
  187. function Extract(item: Pointer): Pointer;
  188. function IndexOf(Item: Pointer): Integer;
  189. function Find(const s:string): Pointer;
  190. function Remove(Item: Pointer): Integer;
  191. procedure Pack;
  192. procedure ShowStatistics;
  193. procedure ForEachCall(proc2call:TListCallback;arg:pointer);
  194. procedure ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  195. property Capacity: Integer read FCapacity write SetCapacity;
  196. property Count: Integer read FCount write SetCount;
  197. property Items[Index: Integer]: Pointer read Get; default;
  198. property List: PHashItemList read FHashList;
  199. property Strs: PChar read FStrs;
  200. end;
  201. {*******************************************************
  202. TFPHashObjectList (From fcl/inc/contnrs.pp)
  203. ********************************************************}
  204. TFPHashObjectList = class;
  205. TFPHashObject = class
  206. private
  207. FOwner : TFPHashObjectList;
  208. FCachedStr : pstring;
  209. FStrIndex : Integer;
  210. protected
  211. function GetName:string;
  212. public
  213. constructor Create(HashObjectList:TFPHashObjectList;const s:string);
  214. property Name:string read GetName;
  215. end;
  216. TFPHashObjectList = class(TObject)
  217. private
  218. FFreeObjects : Boolean;
  219. FHashList: TFPHashList;
  220. function GetCount: integer;
  221. procedure SetCount(const AValue: integer);
  222. protected
  223. function GetItem(Index: Integer): TObject;
  224. procedure SetCapacity(NewCapacity: Integer);
  225. function GetCapacity: integer;
  226. public
  227. constructor Create(FreeObjects : boolean = True);
  228. destructor Destroy; override;
  229. procedure Clear;
  230. function Add(const AName:string;AObject: TObject): Integer;
  231. function NameOfIndex(Index: Integer): String;
  232. procedure Delete(Index: Integer);
  233. function Expand: TFPHashObjectList;
  234. function Extract(Item: TObject): TObject;
  235. function Remove(AObject: TObject): Integer;
  236. function IndexOf(AObject: TObject): Integer;
  237. function Find(const s:string): TObject;
  238. function FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt: Integer): Integer;
  239. procedure Pack;
  240. procedure ShowStatistics;
  241. procedure ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  242. procedure ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  243. property Capacity: Integer read GetCapacity write SetCapacity;
  244. property Count: Integer read GetCount write SetCount;
  245. property OwnsObjects: Boolean read FFreeObjects write FFreeObjects;
  246. property Items[Index: Integer]: TObject read GetItem; default;
  247. property List: TFPHashList read FHashList;
  248. end;
  249. {********************************************
  250. TLinkedList
  251. ********************************************}
  252. type
  253. TLinkedListItem = class
  254. public
  255. Previous,
  256. Next : TLinkedListItem;
  257. Constructor Create;
  258. Destructor Destroy;override;
  259. Function GetCopy:TLinkedListItem;virtual;
  260. end;
  261. TLinkedListItemClass = class of TLinkedListItem;
  262. TLinkedList = class
  263. private
  264. FCount : integer;
  265. FFirst,
  266. FLast : TLinkedListItem;
  267. FNoClear : boolean;
  268. public
  269. constructor Create;
  270. destructor Destroy;override;
  271. { true when the List is empty }
  272. function Empty:boolean;
  273. { deletes all Items }
  274. procedure Clear;
  275. { inserts an Item }
  276. procedure Insert(Item:TLinkedListItem);
  277. { inserts an Item before Loc }
  278. procedure InsertBefore(Item,Loc : TLinkedListItem);
  279. { inserts an Item after Loc }
  280. procedure InsertAfter(Item,Loc : TLinkedListItem);virtual;
  281. { concats an Item }
  282. procedure Concat(Item:TLinkedListItem);
  283. { deletes an Item }
  284. procedure Remove(Item:TLinkedListItem);
  285. { Gets First Item }
  286. function GetFirst:TLinkedListItem;
  287. { Gets last Item }
  288. function GetLast:TLinkedListItem;
  289. { inserts another List at the begin and make this List empty }
  290. procedure insertList(p : TLinkedList);
  291. { inserts another List before the provided item and make this List empty }
  292. procedure insertListBefore(Item:TLinkedListItem;p : TLinkedList);
  293. { inserts another List after the provided item and make this List empty }
  294. procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  295. { concats another List at the end and make this List empty }
  296. procedure concatList(p : TLinkedList);
  297. { concats another List at the start and makes a copy
  298. the list is ordered in reverse.
  299. }
  300. procedure insertListcopy(p : TLinkedList);
  301. { concats another List at the end and makes a copy }
  302. procedure concatListcopy(p : TLinkedList);
  303. property First:TLinkedListItem read FFirst;
  304. property Last:TLinkedListItem read FLast;
  305. property Count:Integer read FCount;
  306. property NoClear:boolean write FNoClear;
  307. end;
  308. {********************************************
  309. TStringList
  310. ********************************************}
  311. { string containerItem }
  312. TStringListItem = class(TLinkedListItem)
  313. FPStr : PString;
  314. public
  315. constructor Create(const s:string);
  316. destructor Destroy;override;
  317. function GetCopy:TLinkedListItem;override;
  318. function Str:string;
  319. end;
  320. { string container }
  321. TStringList = class(TLinkedList)
  322. private
  323. FDoubles : boolean; { if this is set to true, doubles are allowed }
  324. public
  325. constructor Create;
  326. constructor Create_No_Double;
  327. { inserts an Item }
  328. procedure Insert(const s:string);
  329. { concats an Item }
  330. procedure Concat(const s:string);
  331. { deletes an Item }
  332. procedure Remove(const s:string);
  333. { Gets First Item }
  334. function GetFirst:string;
  335. { Gets last Item }
  336. function GetLast:string;
  337. { true if string is in the container, compare case sensitive }
  338. function FindCase(const s:string):TStringListItem;
  339. { true if string is in the container }
  340. function Find(const s:string):TStringListItem;
  341. { inserts an item }
  342. procedure InsertItem(item:TStringListItem);
  343. { concats an item }
  344. procedure ConcatItem(item:TStringListItem);
  345. property Doubles:boolean read FDoubles write FDoubles;
  346. procedure readstream(f:TCStream);
  347. procedure writestream(f:TCStream);
  348. end;
  349. {********************************************
  350. Dictionary
  351. ********************************************}
  352. const
  353. { the real size will be [0..hasharray-1] ! }
  354. hasharraysize = 512;
  355. type
  356. { namedindexobect for use with dictionary and indexarray }
  357. TNamedIndexItem=class
  358. private
  359. { indexarray }
  360. FIndexNr : integer;
  361. FIndexNext : TNamedIndexItem;
  362. { dictionary }
  363. FLeft,
  364. FRight : TNamedIndexItem;
  365. FSpeedValue : cardinal;
  366. FName : Pstring;
  367. protected
  368. function GetName:string;virtual;
  369. procedure SetName(const n:string);virtual;
  370. public
  371. constructor Create;
  372. constructor CreateName(const n:string);
  373. destructor Destroy;override;
  374. property IndexNr:integer read FIndexNr write FIndexNr;
  375. property IndexNext:TNamedIndexItem read FIndexNext write FIndexNext;
  376. property Name:string read GetName write SetName;
  377. property SpeedValue:cardinal read FSpeedValue;
  378. property Left:TNamedIndexItem read FLeft write FLeft;
  379. property Right:TNamedIndexItem read FRight write FRight;
  380. end;
  381. Pdictionaryhasharray=^Tdictionaryhasharray;
  382. Tdictionaryhasharray=array[0..hasharraysize-1] of TNamedIndexItem;
  383. TnamedIndexCallback = procedure(p:TNamedIndexItem;arg:pointer) of object;
  384. TnamedIndexStaticCallback = procedure(p:TNamedIndexItem;arg:pointer);
  385. Tdictionary=class
  386. private
  387. FRoot : TNamedIndexItem;
  388. FCount : longint;
  389. FHashArray : Pdictionaryhasharray;
  390. procedure cleartree(var obj:TNamedIndexItem);
  391. function insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  392. procedure inserttree(currtree,currroot:TNamedIndexItem);
  393. public
  394. noclear : boolean;
  395. delete_doubles : boolean;
  396. constructor Create;
  397. destructor Destroy;override;
  398. procedure usehash;
  399. procedure clear;
  400. function delete(const s:string):TNamedIndexItem;
  401. function empty:boolean;
  402. procedure foreach(proc2call:TNamedIndexcallback;arg:pointer);
  403. procedure foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  404. function insert(obj:TNamedIndexItem):TNamedIndexItem;
  405. function replace(oldobj,newobj:TNamedIndexItem):boolean;
  406. function rename(const olds,News : string):TNamedIndexItem;
  407. function search(const s:string):TNamedIndexItem;
  408. function speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  409. property Items[const s:string]:TNamedIndexItem read Search;default;
  410. property Count:longint read FCount;
  411. end;
  412. tindexobjectarray=array[1..16000] of TNamedIndexItem;
  413. pnamedindexobjectarray=^tindexobjectarray;
  414. tindexarray=class
  415. noclear : boolean;
  416. First : TNamedIndexItem;
  417. count : integer;
  418. constructor Create(Agrowsize:integer);
  419. destructor destroy;override;
  420. procedure clear;
  421. procedure foreach(proc2call : Tnamedindexcallback;arg:pointer);
  422. procedure foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  423. procedure deleteindex(p:TNamedIndexItem);
  424. procedure delete(var p:TNamedIndexItem);
  425. procedure insert(p:TNamedIndexItem);
  426. procedure replace(oldp,newp:TNamedIndexItem);
  427. function search(nr:integer):TNamedIndexItem;
  428. property Items[Index: Integer]: TNamedIndexItem read Search; default;
  429. private
  430. growsize,
  431. size : integer;
  432. data : pnamedindexobjectarray;
  433. procedure grow(gsize:integer);
  434. end;
  435. {********************************************
  436. DynamicArray
  437. ********************************************}
  438. const
  439. dynamicblockbasesize = 12;
  440. type
  441. pdynamicblock = ^tdynamicblock;
  442. tdynamicblock = record
  443. pos,
  444. used : integer;
  445. Next : pdynamicblock;
  446. { can't use sizeof(integer) because it crashes gdb }
  447. data : array[0..1024*1024] of byte;
  448. end;
  449. tdynamicarray = class
  450. private
  451. FPosn : integer;
  452. FPosnblock : pdynamicblock;
  453. FBlocksize : integer;
  454. FFirstblock,
  455. FLastblock : pdynamicblock;
  456. procedure grow;
  457. public
  458. constructor Create(Ablocksize:integer);
  459. destructor Destroy;override;
  460. procedure reset;
  461. function size:integer;
  462. procedure align(i:integer);
  463. procedure seek(i:integer);
  464. function read(var d;len:integer):integer;
  465. procedure write(const d;len:integer);
  466. procedure writestr(const s:string);
  467. procedure readstream(f:TCStream;maxlen:longint);
  468. procedure writestream(f:TCStream);
  469. property BlockSize : integer read FBlocksize;
  470. property FirstBlock : PDynamicBlock read FFirstBlock;
  471. property Pos : integer read FPosn;
  472. end;
  473. Const WeightDefault = 1000;
  474. Type
  475. TLinkRec = record
  476. Key : AnsiString;
  477. Value : AnsiString; // key expands to valuelist "value"
  478. Weight: longint;
  479. end;
  480. TLinkStrMap = class
  481. private
  482. itemcnt : longint;
  483. fmap : Array Of TLinkRec;
  484. function Lookup(key:Ansistring):longint;
  485. function getlinkrec(i:longint):TLinkRec;
  486. public
  487. procedure Add(key:ansistring;value:AnsiString='';weight:longint=weightdefault);
  488. procedure addseries(keys:AnsiString;weight:longint=weightdefault);
  489. function AddDep(keyvalue:String):boolean;
  490. function AddWeight(keyvalue:String):boolean;
  491. procedure SetValue(key:AnsiString;Weight:Integer);
  492. procedure SortonWeight;
  493. function Find(key:AnsiString):AnsiString;
  494. procedure Expand(src:TStringList;dest: TLinkStrMap);
  495. procedure UpdateWeights(Weightmap:TLinkStrMap);
  496. constructor Create;
  497. property count : longint read itemcnt;
  498. property items[I:longint]:TLinkRec read getlinkrec; default;
  499. end;
  500. implementation
  501. {*****************************************************************************
  502. Memory debug
  503. *****************************************************************************}
  504. constructor tmemdebug.create(const s:string);
  505. begin
  506. infostr:=s;
  507. totalmem:=0;
  508. Start;
  509. end;
  510. procedure tmemdebug.start;
  511. var
  512. status : TFPCHeapStatus;
  513. begin
  514. status:=GetFPCHeapStatus;
  515. startmem:=status.CurrHeapUsed;
  516. end;
  517. procedure tmemdebug.stop;
  518. var
  519. status : TFPCHeapStatus;
  520. begin
  521. if startmem<>0 then
  522. begin
  523. status:=GetFPCHeapStatus;
  524. inc(TotalMem,startmem-status.CurrHeapUsed);
  525. startmem:=0;
  526. end;
  527. end;
  528. destructor tmemdebug.destroy;
  529. begin
  530. Stop;
  531. show;
  532. end;
  533. procedure tmemdebug.show;
  534. begin
  535. write('memory [',infostr,'] ');
  536. if TotalMem>0 then
  537. writeln(DStr(TotalMem shr 10),' Kb released')
  538. else
  539. writeln(DStr((-TotalMem) shr 10),' Kb allocated');
  540. end;
  541. {*****************************************************************************
  542. TFPObjectList (Copied from rtl/objpas/classes/lists.inc)
  543. *****************************************************************************}
  544. Const
  545. // Ratio of Pointer and Word Size.
  546. WordRatio = SizeOf(Pointer) Div SizeOf(Word);
  547. procedure TFPList.RaiseIndexError(Index : Integer);
  548. begin
  549. Error(SListIndexError, Index);
  550. end;
  551. function TFPList.Get(Index: Integer): Pointer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  552. begin
  553. If (Index < 0) or (Index >= FCount) then
  554. RaiseIndexError(Index);
  555. Result:=FList^[Index];
  556. end;
  557. procedure TFPList.Put(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  558. begin
  559. if (Index < 0) or (Index >= FCount) then
  560. RaiseIndexError(Index);
  561. Flist^[Index] := Item;
  562. end;
  563. function TFPList.Extract(item: Pointer): Pointer;
  564. var
  565. i : Integer;
  566. begin
  567. result := nil;
  568. i := IndexOf(item);
  569. if i >= 0 then
  570. begin
  571. Result := item;
  572. FList^[i] := nil;
  573. Delete(i);
  574. end;
  575. end;
  576. procedure TFPList.SetCapacity(NewCapacity: Integer);
  577. begin
  578. If (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
  579. Error (SListCapacityError, NewCapacity);
  580. if NewCapacity = FCapacity then
  581. exit;
  582. ReallocMem(FList, SizeOf(Pointer)*NewCapacity);
  583. FCapacity := NewCapacity;
  584. end;
  585. procedure TFPList.SetCount(NewCount: Integer);
  586. begin
  587. if (NewCount < 0) or (NewCount > MaxListSize)then
  588. Error(SListCountError, NewCount);
  589. If NewCount > FCount then
  590. begin
  591. If NewCount > FCapacity then
  592. SetCapacity(NewCount);
  593. If FCount < NewCount then
  594. FillWord(Flist^[FCount], (NewCount-FCount) * WordRatio, 0);
  595. end;
  596. FCount := Newcount;
  597. end;
  598. destructor TFPList.Destroy;
  599. begin
  600. Self.Clear;
  601. inherited Destroy;
  602. end;
  603. function TFPList.Add(Item: Pointer): Integer; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  604. begin
  605. if FCount = FCapacity then
  606. Self.Expand;
  607. FList^[FCount] := Item;
  608. Result := FCount;
  609. FCount := FCount + 1;
  610. end;
  611. procedure TFPList.Clear;
  612. begin
  613. if Assigned(FList) then
  614. begin
  615. SetCount(0);
  616. SetCapacity(0);
  617. FList := nil;
  618. end;
  619. end;
  620. procedure TFPList.Delete(Index: Integer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  621. begin
  622. If (Index<0) or (Index>=FCount) then
  623. Error (SListIndexError, Index);
  624. FCount := FCount-1;
  625. System.Move (FList^[Index+1], FList^[Index], (FCount - Index) * SizeOf(Pointer));
  626. // Shrink the list if appropriate
  627. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  628. begin
  629. FCapacity := FCapacity shr 1;
  630. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  631. end;
  632. end;
  633. class procedure TFPList.Error(const Msg: string; Data: PtrInt);
  634. begin
  635. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  636. end;
  637. procedure TFPList.Exchange(Index1, Index2: Integer);
  638. var
  639. Temp : Pointer;
  640. begin
  641. If ((Index1 >= FCount) or (Index1 < 0)) then
  642. Error(SListIndexError, Index1);
  643. If ((Index2 >= FCount) or (Index2 < 0)) then
  644. Error(SListIndexError, Index2);
  645. Temp := FList^[Index1];
  646. FList^[Index1] := FList^[Index2];
  647. FList^[Index2] := Temp;
  648. end;
  649. function TFPList.Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  650. var
  651. IncSize : Longint;
  652. begin
  653. if FCount < FCapacity then exit;
  654. IncSize := 4;
  655. if FCapacity > 3 then IncSize := IncSize + 4;
  656. if FCapacity > 8 then IncSize := IncSize+8;
  657. if FCapacity > 127 then Inc(IncSize, FCapacity shr 2);
  658. SetCapacity(FCapacity + IncSize);
  659. Result := Self;
  660. end;
  661. function TFPList.First: Pointer;
  662. begin
  663. If FCount = 0 then
  664. Result := Nil
  665. else
  666. Result := Items[0];
  667. end;
  668. function TFPList.IndexOf(Item: Pointer): Integer;
  669. begin
  670. Result := 0;
  671. while(Result < FCount) and (Flist^[Result] <> Item) do Result := Result + 1;
  672. If Result = FCount then Result := -1;
  673. end;
  674. procedure TFPList.Insert(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
  675. begin
  676. if (Index < 0) or (Index > FCount )then
  677. Error(SlistIndexError, Index);
  678. iF FCount = FCapacity then Self.Expand;
  679. if Index<FCount then
  680. System.Move(Flist^[Index], Flist^[Index+1], (FCount - Index) * SizeOf(Pointer));
  681. FList^[Index] := Item;
  682. FCount := FCount + 1;
  683. end;
  684. function TFPList.Last: Pointer;
  685. begin
  686. { Wouldn't it be better to return nil if the count is zero ?}
  687. If FCount = 0 then
  688. Result := nil
  689. else
  690. Result := Items[FCount - 1];
  691. end;
  692. procedure TFPList.Move(CurIndex, NewIndex: Integer);
  693. var
  694. Temp : Pointer;
  695. begin
  696. if ((CurIndex < 0) or (CurIndex > Count - 1)) then
  697. Error(SListIndexError, CurIndex);
  698. if (NewINdex < 0) then
  699. Error(SlistIndexError, NewIndex);
  700. Temp := FList^[CurIndex];
  701. FList^[CurIndex] := nil;
  702. Self.Delete(CurIndex);
  703. Self.Insert(NewIndex, nil);
  704. FList^[NewIndex] := Temp;
  705. end;
  706. function TFPList.Remove(Item: Pointer): Integer;
  707. begin
  708. Result := IndexOf(Item);
  709. If Result <> -1 then
  710. Self.Delete(Result);
  711. end;
  712. procedure TFPList.Pack;
  713. var
  714. NewCount,
  715. i : integer;
  716. pdest,
  717. psrc : PPointer;
  718. begin
  719. NewCount:=0;
  720. psrc:=@FList[0];
  721. pdest:=psrc;
  722. For I:=0 To FCount-1 Do
  723. begin
  724. if assigned(psrc^) then
  725. begin
  726. pdest^:=psrc^;
  727. inc(pdest);
  728. inc(NewCount);
  729. end;
  730. inc(psrc);
  731. end;
  732. FCount:=NewCount;
  733. end;
  734. // Needed by Sort method.
  735. Procedure QuickSort(FList: PPointerList; L, R : Longint;
  736. Compare: TListSortCompare);
  737. var
  738. I, J : Longint;
  739. P, Q : Pointer;
  740. begin
  741. repeat
  742. I := L;
  743. J := R;
  744. P := FList^[ (L + R) div 2 ];
  745. repeat
  746. while Compare(P, FList^[i]) > 0 do
  747. I := I + 1;
  748. while Compare(P, FList^[J]) < 0 do
  749. J := J - 1;
  750. If I <= J then
  751. begin
  752. Q := FList^[I];
  753. Flist^[I] := FList^[J];
  754. FList^[J] := Q;
  755. I := I + 1;
  756. J := J - 1;
  757. end;
  758. until I > J;
  759. if L < J then
  760. QuickSort(FList, L, J, Compare);
  761. L := I;
  762. until I >= R;
  763. end;
  764. procedure TFPList.Sort(Compare: TListSortCompare);
  765. begin
  766. if Not Assigned(FList) or (FCount < 2) then exit;
  767. QuickSort(Flist, 0, FCount-1, Compare);
  768. end;
  769. procedure TFPList.Assign(Obj: TFPList);
  770. var
  771. i: Integer;
  772. begin
  773. Clear;
  774. for I := 0 to Obj.Count - 1 do
  775. Add(Obj[i]);
  776. end;
  777. procedure TFPList.ForEachCall(proc2call:TListCallback;arg:pointer);
  778. var
  779. i : integer;
  780. p : pointer;
  781. begin
  782. For I:=0 To Count-1 Do
  783. begin
  784. p:=FList^[i];
  785. if assigned(p) then
  786. proc2call(p,arg);
  787. end;
  788. end;
  789. procedure TFPList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  790. var
  791. i : integer;
  792. p : pointer;
  793. begin
  794. For I:=0 To Count-1 Do
  795. begin
  796. p:=FList^[i];
  797. if assigned(p) then
  798. proc2call(p,arg);
  799. end;
  800. end;
  801. {*****************************************************************************
  802. TFPObjectList (Copied from rtl/objpas/classes/lists.inc)
  803. *****************************************************************************}
  804. constructor TFPObjectList.Create(FreeObjects : boolean);
  805. begin
  806. Create;
  807. FFreeObjects := Freeobjects;
  808. end;
  809. destructor TFPObjectList.Destroy;
  810. begin
  811. if (FList <> nil) then
  812. begin
  813. Clear;
  814. FList.Destroy;
  815. end;
  816. inherited Destroy;
  817. end;
  818. procedure TFPObjectList.Clear;
  819. var
  820. i: integer;
  821. begin
  822. if FFreeObjects then
  823. for i := 0 to FList.Count - 1 do
  824. TObject(FList[i]).Free;
  825. FList.Clear;
  826. end;
  827. constructor TFPObjectList.Create;
  828. begin
  829. inherited Create;
  830. FList := TFPList.Create;
  831. FFreeObjects := True;
  832. end;
  833. function TFPObjectList.GetCount: integer;
  834. begin
  835. Result := FList.Count;
  836. end;
  837. procedure TFPObjectList.SetCount(const AValue: integer);
  838. begin
  839. if FList.Count <> AValue then
  840. FList.Count := AValue;
  841. end;
  842. function TFPObjectList.GetItem(Index: Integer): TObject; {$ifdef CLASSESINLINE}inline;{$endif}
  843. begin
  844. Result := TObject(FList[Index]);
  845. end;
  846. procedure TFPObjectList.SetItem(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  847. begin
  848. if OwnsObjects then
  849. TObject(FList[Index]).Free;
  850. FList[index] := AObject;
  851. end;
  852. procedure TFPObjectList.SetCapacity(NewCapacity: Integer);
  853. begin
  854. FList.Capacity := NewCapacity;
  855. end;
  856. function TFPObjectList.GetCapacity: integer;
  857. begin
  858. Result := FList.Capacity;
  859. end;
  860. function TFPObjectList.Add(AObject: TObject): Integer; {$ifdef CLASSESINLINE}inline;{$endif}
  861. begin
  862. Result := FList.Add(AObject);
  863. end;
  864. procedure TFPObjectList.Delete(Index: Integer); {$ifdef CLASSESINLINE}inline;{$endif}
  865. begin
  866. if OwnsObjects then
  867. TObject(FList[Index]).Free;
  868. FList.Delete(Index);
  869. end;
  870. procedure TFPObjectList.Exchange(Index1, Index2: Integer);
  871. begin
  872. FList.Exchange(Index1, Index2);
  873. end;
  874. function TFPObjectList.Expand: TFPObjectList;
  875. begin
  876. FList.Expand;
  877. Result := Self;
  878. end;
  879. function TFPObjectList.Extract(Item: TObject): TObject;
  880. begin
  881. Result := TObject(FList.Extract(Item));
  882. end;
  883. function TFPObjectList.Remove(AObject: TObject): Integer;
  884. begin
  885. Result := IndexOf(AObject);
  886. if (Result <> -1) then
  887. begin
  888. if OwnsObjects then
  889. TObject(FList[Result]).Free;
  890. FList.Delete(Result);
  891. end;
  892. end;
  893. function TFPObjectList.IndexOf(AObject: TObject): Integer;
  894. begin
  895. Result := FList.IndexOf(Pointer(AObject));
  896. end;
  897. function TFPObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  898. var
  899. I : Integer;
  900. begin
  901. I:=AStartAt;
  902. Result:=-1;
  903. If AExact then
  904. while (I<Count) and (Result=-1) do
  905. If Items[i].ClassType=AClass then
  906. Result:=I
  907. else
  908. Inc(I)
  909. else
  910. while (I<Count) and (Result=-1) do
  911. If Items[i].InheritsFrom(AClass) then
  912. Result:=I
  913. else
  914. Inc(I);
  915. end;
  916. procedure TFPObjectList.Insert(Index: Integer; AObject: TObject); {$ifdef CLASSESINLINE}inline;{$endif}
  917. begin
  918. FList.Insert(Index, Pointer(AObject));
  919. end;
  920. procedure TFPObjectList.Move(CurIndex, NewIndex: Integer);
  921. begin
  922. FList.Move(CurIndex, NewIndex);
  923. end;
  924. procedure TFPObjectList.Assign(Obj: TFPObjectList);
  925. var
  926. i: Integer;
  927. begin
  928. Clear;
  929. for I := 0 to Obj.Count - 1 do
  930. Add(Obj[i]);
  931. end;
  932. procedure TFPObjectList.Pack;
  933. begin
  934. FList.Pack;
  935. end;
  936. procedure TFPObjectList.Sort(Compare: TListSortCompare);
  937. begin
  938. FList.Sort(Compare);
  939. end;
  940. function TFPObjectList.First: TObject;
  941. begin
  942. Result := TObject(FList.First);
  943. end;
  944. function TFPObjectList.Last: TObject;
  945. begin
  946. Result := TObject(FList.Last);
  947. end;
  948. procedure TFPObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  949. begin
  950. FList.ForEachCall(TListCallBack(proc2call),arg);
  951. end;
  952. procedure TFPObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  953. begin
  954. FList.ForEachCall(TListStaticCallBack(proc2call),arg);
  955. end;
  956. {*****************************************************************************
  957. TFPHashList
  958. *****************************************************************************}
  959. function FPHash1(const s:string):LongWord;
  960. Var
  961. g : LongWord;
  962. p,pmax : pchar;
  963. begin
  964. result:=0;
  965. p:=@s[1];
  966. pmax:=@s[length(s)+1];
  967. while (p<pmax) do
  968. begin
  969. result:=result shl 4 + LongWord(p^);
  970. g:=result and LongWord($F0000000);
  971. if g<>0 then
  972. result:=result xor (g shr 24) xor g;
  973. inc(p);
  974. end;
  975. If result=0 then
  976. result:=$ffffffff;
  977. end;
  978. function FPHash(const s:string):LongWord;
  979. Var
  980. p,pmax : pchar;
  981. begin
  982. {$ifopt Q+}
  983. {$define overflowon}
  984. {$Q-}
  985. {$endif}
  986. result:=0;
  987. p:=@s[1];
  988. pmax:=@s[length(s)+1];
  989. while (p<pmax) do
  990. begin
  991. result:=LongWord((result shl 5) - result) xor LongWord(P^);
  992. inc(p);
  993. end;
  994. {$ifdef overflowon}
  995. {$Q+}
  996. {$undef overflowon}
  997. {$endif}
  998. end;
  999. procedure TFPHashList.RaiseIndexError(Index : Integer);
  1000. begin
  1001. Error(SListIndexError, Index);
  1002. end;
  1003. function TFPHashList.Get(Index: Integer): Pointer;
  1004. begin
  1005. If (Index < 0) or (Index >= FCount) then
  1006. RaiseIndexError(Index);
  1007. Result:=FHashList^[Index].Data;
  1008. end;
  1009. function TFPHashList.NameOfIndex(Index: Integer): String;
  1010. begin
  1011. If (Index < 0) or (Index >= FCount) then
  1012. RaiseIndexError(Index);
  1013. Result:=PShortString(@FStrs[FHashList^[Index].StrIndex])^;
  1014. end;
  1015. function TFPHashList.Extract(item: Pointer): Pointer;
  1016. var
  1017. i : Integer;
  1018. begin
  1019. result := nil;
  1020. i := IndexOf(item);
  1021. if i >= 0 then
  1022. begin
  1023. Result := item;
  1024. Delete(i);
  1025. end;
  1026. end;
  1027. procedure TFPHashList.SetCapacity(NewCapacity: Integer);
  1028. begin
  1029. If (NewCapacity < FCount) or (NewCapacity > MaxHashListSize) then
  1030. Error (SListCapacityError, NewCapacity);
  1031. if NewCapacity = FCapacity then
  1032. exit;
  1033. ReallocMem(FHashList, NewCapacity*SizeOf(THashItem));
  1034. FCapacity := NewCapacity;
  1035. end;
  1036. procedure TFPHashList.SetCount(NewCount: Integer);
  1037. begin
  1038. if (NewCount < 0) or (NewCount > MaxHashListSize)then
  1039. Error(SListCountError, NewCount);
  1040. If NewCount > FCount then
  1041. begin
  1042. If NewCount > FCapacity then
  1043. SetCapacity(NewCount);
  1044. If FCount < NewCount then
  1045. FillChar(FHashList^[FCount], (NewCount-FCount) div Sizeof(THashItem), 0);
  1046. end;
  1047. FCount := Newcount;
  1048. end;
  1049. procedure TFPHashList.SetStrCapacity(NewCapacity: Integer);
  1050. begin
  1051. If (NewCapacity < FStrCount) or (NewCapacity > MaxHashStrSize) then
  1052. Error (SListCapacityError, NewCapacity);
  1053. if NewCapacity = FStrCapacity then
  1054. exit;
  1055. ReallocMem(FStrs, NewCapacity);
  1056. FStrCapacity := NewCapacity;
  1057. end;
  1058. procedure TFPHashList.SetHashCapacity(NewCapacity: Integer);
  1059. begin
  1060. If (NewCapacity < 1) then
  1061. Error (SListCapacityError, NewCapacity);
  1062. if FHashCapacity=NewCapacity then
  1063. exit;
  1064. FHashCapacity:=NewCapacity;
  1065. ReallocMem(FHashTable, FHashCapacity*sizeof(Integer));
  1066. ReHash;
  1067. end;
  1068. procedure TFPHashList.ReHash;
  1069. var
  1070. i : Integer;
  1071. begin
  1072. FillDword(FHashTable^,FHashCapacity,LongWord(-1));
  1073. For i:=0 To FCount-1 Do
  1074. AddToHashTable(i);
  1075. end;
  1076. constructor TFPHashList.Create;
  1077. begin
  1078. SetHashCapacity(1);
  1079. end;
  1080. destructor TFPHashList.Destroy;
  1081. begin
  1082. Clear;
  1083. if assigned(FHashTable) then
  1084. FreeMem(FHashTable);
  1085. inherited Destroy;
  1086. end;
  1087. function TFPHashList.AddStr(const s:string): Integer;
  1088. var
  1089. Len : Integer;
  1090. begin
  1091. len:=length(s)+1;
  1092. if FStrCount+Len >= FStrCapacity then
  1093. StrExpand(Len);
  1094. System.Move(s[0],FStrs[FStrCount],Len);
  1095. result:=FStrCount;
  1096. inc(FStrCount,Len);
  1097. end;
  1098. procedure TFPHashList.AddToHashTable(Index: Integer);
  1099. var
  1100. HashIndex : Integer;
  1101. begin
  1102. with FHashList^[Index] do
  1103. begin
  1104. if not assigned(Data) then
  1105. exit;
  1106. HashIndex:=HashValue mod LongWord(FHashCapacity);
  1107. NextIndex:=FHashTable^[HashIndex];
  1108. FHashTable^[HashIndex]:=Index;
  1109. end;
  1110. end;
  1111. function TFPHashList.Add(const AName:string;Item: Pointer): Integer;
  1112. begin
  1113. if FCount = FCapacity then
  1114. Expand;
  1115. with FHashList^[FCount] do
  1116. begin
  1117. HashValue:=FPHash(AName);
  1118. Data:=Item;
  1119. StrIndex:=AddStr(AName);
  1120. end;
  1121. AddToHashTable(FCount);
  1122. Result := FCount;
  1123. inc(FCount);
  1124. end;
  1125. procedure TFPHashList.Clear;
  1126. begin
  1127. if Assigned(FHashList) then
  1128. begin
  1129. FCount:=0;
  1130. SetCapacity(0);
  1131. FHashList := nil;
  1132. end;
  1133. SetHashCapacity(1);
  1134. if Assigned(FStrs) then
  1135. begin
  1136. FStrCount:=0;
  1137. SetStrCapacity(0);
  1138. FStrs := nil;
  1139. end;
  1140. end;
  1141. procedure TFPHashList.Delete(Index: Integer);
  1142. begin
  1143. If (Index<0) or (Index>=FCount) then
  1144. Error (SListIndexError, Index);
  1145. FHashList^[Index].Data:=nil;
  1146. end;
  1147. class procedure TFPHashList.Error(const Msg: string; Data: PtrInt);
  1148. begin
  1149. Raise EListError.CreateFmt(Msg,[Data]) at get_caller_addr(get_frame);
  1150. end;
  1151. function TFPHashList.Expand: TFPHashList;
  1152. var
  1153. IncSize : Longint;
  1154. begin
  1155. Result := Self;
  1156. if FCount < FCapacity then
  1157. exit;
  1158. IncSize := 4;
  1159. if FCapacity > 127 then
  1160. Inc(IncSize, FCapacity shr 2)
  1161. else if FCapacity > 8 then
  1162. inc(IncSize,8)
  1163. else if FCapacity > 3 then
  1164. inc(IncSize,4);
  1165. SetCapacity(FCapacity + IncSize);
  1166. { Maybe expand hash also }
  1167. if FCount>FHashCapacity*MaxItemsPerHash then
  1168. SetHashCapacity(FCount div MaxItemsPerHash);
  1169. end;
  1170. procedure TFPHashList.StrExpand(MinIncSize:Integer);
  1171. var
  1172. IncSize : Longint;
  1173. begin
  1174. if FStrCount+MinIncSize < FStrCapacity then
  1175. exit;
  1176. IncSize := 64+MinIncSize;
  1177. if FStrCapacity > 255 then
  1178. Inc(IncSize, FStrCapacity shr 2);
  1179. SetStrCapacity(FStrCapacity + IncSize);
  1180. end;
  1181. function TFPHashList.IndexOf(Item: Pointer): Integer;
  1182. begin
  1183. Result := 0;
  1184. while(Result < FCount) and (FHashList^[Result].Data <> Item) do Result := Result + 1;
  1185. If Result = FCount then Result := -1;
  1186. end;
  1187. function TFPHashList.Find(const s:string): Pointer;
  1188. var
  1189. CurrHash : LongWord;
  1190. Index,
  1191. HashIndex : Integer;
  1192. Len,
  1193. LastChar : Char;
  1194. begin
  1195. CurrHash:=FPHash(s);
  1196. HashIndex:=CurrHash mod LongWord(FHashCapacity);
  1197. Index:=FHashTable^[HashIndex];
  1198. Len:=Char(Length(s));
  1199. LastChar:=s[Byte(Len)];
  1200. while Index<>-1 do
  1201. begin
  1202. with FHashList^[Index] do
  1203. begin
  1204. if assigned(Data) and
  1205. (HashValue=CurrHash) and
  1206. (Len=FStrs[StrIndex]) and
  1207. (LastChar=FStrs[StrIndex+Byte(Len)]) and
  1208. (s=PShortString(@FStrs[StrIndex])^) then
  1209. begin
  1210. Result:=Data;
  1211. exit;
  1212. end;
  1213. Index:=NextIndex;
  1214. end;
  1215. end;
  1216. Result:=nil;
  1217. end;
  1218. function TFPHashList.Remove(Item: Pointer): Integer;
  1219. begin
  1220. Result := IndexOf(Item);
  1221. If Result <> -1 then
  1222. Self.Delete(Result);
  1223. end;
  1224. procedure TFPHashList.Pack;
  1225. var
  1226. NewCount,
  1227. i : integer;
  1228. pdest,
  1229. psrc : PHashItem;
  1230. begin
  1231. NewCount:=0;
  1232. psrc:=@FHashList[0];
  1233. pdest:=psrc;
  1234. For I:=0 To FCount-1 Do
  1235. begin
  1236. if assigned(psrc^.Data) then
  1237. begin
  1238. pdest^:=psrc^;
  1239. inc(pdest);
  1240. inc(NewCount);
  1241. end;
  1242. inc(psrc);
  1243. end;
  1244. FCount:=NewCount;
  1245. { We need to ReHash to update the IndexNext }
  1246. ReHash;
  1247. { Release over-capacity }
  1248. SetCapacity(FCount);
  1249. SetStrCapacity(FStrCount);
  1250. end;
  1251. procedure TFPHashList.ShowStatistics;
  1252. var
  1253. HashMean,
  1254. HashStdDev : Double;
  1255. Index,
  1256. i,j : Integer;
  1257. begin
  1258. { Calculate Mean and StdDev }
  1259. HashMean:=0;
  1260. HashStdDev:=0;
  1261. for i:=0 to FHashCapacity-1 do
  1262. begin
  1263. j:=0;
  1264. Index:=FHashTable^[i];
  1265. while (Index<>-1) do
  1266. begin
  1267. inc(j);
  1268. Index:=FHashList^[Index].NextIndex;
  1269. end;
  1270. HashMean:=HashMean+j;
  1271. HashStdDev:=HashStdDev+Sqr(j);
  1272. end;
  1273. HashMean:=HashMean/FHashCapacity;
  1274. HashStdDev:=(HashStdDev-FHashCapacity*Sqr(HashMean));
  1275. If FHashCapacity>1 then
  1276. HashStdDev:=Sqrt(HashStdDev/(FHashCapacity-1))
  1277. else
  1278. HashStdDev:=0;
  1279. { Print info to stdout }
  1280. Writeln('HashSize : ',FHashCapacity);
  1281. Writeln('HashMean : ',HashMean:1:4);
  1282. Writeln('HashStdDev : ',HashStdDev:1:4);
  1283. Writeln('ListSize : ',FCount,'/',FCapacity);
  1284. Writeln('StringSize : ',FStrCount,'/',FStrCapacity);
  1285. end;
  1286. procedure TFPHashList.ForEachCall(proc2call:TListCallback;arg:pointer);
  1287. var
  1288. i : integer;
  1289. p : pointer;
  1290. begin
  1291. For I:=0 To Count-1 Do
  1292. begin
  1293. p:=FHashList^[i].Data;
  1294. if assigned(p) then
  1295. proc2call(p,arg);
  1296. end;
  1297. end;
  1298. procedure TFPHashList.ForEachCall(proc2call:TListStaticCallback;arg:pointer);
  1299. var
  1300. i : integer;
  1301. p : pointer;
  1302. begin
  1303. For I:=0 To Count-1 Do
  1304. begin
  1305. p:=FHashList^[i].Data;
  1306. if assigned(p) then
  1307. proc2call(p,arg);
  1308. end;
  1309. end;
  1310. {*****************************************************************************
  1311. TFPHashObject
  1312. *****************************************************************************}
  1313. constructor TFPHashObject.Create(HashObjectList:TFPHashObjectList;const s:string);
  1314. var
  1315. Index : Integer;
  1316. begin
  1317. FOwner:=HashObjectList;
  1318. Index:=HashObjectList.Add(s,Self);
  1319. FStrIndex:=HashObjectList.List.List^[Index].StrIndex;
  1320. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1321. end;
  1322. function TFPHashObject.GetName:string;
  1323. begin
  1324. FCachedStr:=PShortString(@FOwner.List.Strs[FStrIndex]);
  1325. Result:=FCachedStr^;
  1326. end;
  1327. {*****************************************************************************
  1328. TFPHashObjectList (Copied from rtl/objpas/classes/lists.inc)
  1329. *****************************************************************************}
  1330. constructor TFPHashObjectList.Create(FreeObjects : boolean = True);
  1331. begin
  1332. inherited Create;
  1333. FHashList := TFPHashList.Create;
  1334. FFreeObjects := Freeobjects;
  1335. end;
  1336. destructor TFPHashObjectList.Destroy;
  1337. begin
  1338. if (FHashList <> nil) then
  1339. begin
  1340. Clear;
  1341. FHashList.Destroy;
  1342. end;
  1343. inherited Destroy;
  1344. end;
  1345. procedure TFPHashObjectList.Clear;
  1346. var
  1347. i: integer;
  1348. begin
  1349. if FFreeObjects then
  1350. for i := 0 to FHashList.Count - 1 do
  1351. TObject(FHashList[i]).Free;
  1352. FHashList.Clear;
  1353. end;
  1354. function TFPHashObjectList.GetCount: integer;
  1355. begin
  1356. Result := FHashList.Count;
  1357. end;
  1358. procedure TFPHashObjectList.SetCount(const AValue: integer);
  1359. begin
  1360. if FHashList.Count <> AValue then
  1361. FHashList.Count := AValue;
  1362. end;
  1363. function TFPHashObjectList.GetItem(Index: Integer): TObject;
  1364. begin
  1365. Result := TObject(FHashList[Index]);
  1366. end;
  1367. procedure TFPHashObjectList.SetCapacity(NewCapacity: Integer);
  1368. begin
  1369. FHashList.Capacity := NewCapacity;
  1370. end;
  1371. function TFPHashObjectList.GetCapacity: integer;
  1372. begin
  1373. Result := FHashList.Capacity;
  1374. end;
  1375. function TFPHashObjectList.Add(const AName:string;AObject: TObject): Integer;
  1376. begin
  1377. Result := FHashList.Add(AName,AObject);
  1378. end;
  1379. function TFPHashObjectList.NameOfIndex(Index: Integer): String;
  1380. begin
  1381. Result := FHashList.NameOfIndex(Index);
  1382. end;
  1383. procedure TFPHashObjectList.Delete(Index: Integer);
  1384. begin
  1385. if OwnsObjects then
  1386. TObject(FHashList[Index]).Free;
  1387. FHashList.Delete(Index);
  1388. end;
  1389. function TFPHashObjectList.Expand: TFPHashObjectList;
  1390. begin
  1391. FHashList.Expand;
  1392. Result := Self;
  1393. end;
  1394. function TFPHashObjectList.Extract(Item: TObject): TObject;
  1395. begin
  1396. Result := TObject(FHashList.Extract(Item));
  1397. end;
  1398. function TFPHashObjectList.Remove(AObject: TObject): Integer;
  1399. begin
  1400. Result := IndexOf(AObject);
  1401. if (Result <> -1) then
  1402. begin
  1403. if OwnsObjects then
  1404. TObject(FHashList[Result]).Free;
  1405. FHashList.Delete(Result);
  1406. end;
  1407. end;
  1408. function TFPHashObjectList.IndexOf(AObject: TObject): Integer;
  1409. begin
  1410. Result := FHashList.IndexOf(Pointer(AObject));
  1411. end;
  1412. function TFPHashObjectList.Find(const s:string): TObject;
  1413. begin
  1414. result:=TObject(FHashList.Find(s));
  1415. end;
  1416. function TFPHashObjectList.FindInstanceOf(AClass: TClass; AExact: Boolean; AStartAt : Integer): Integer;
  1417. var
  1418. I : Integer;
  1419. begin
  1420. I:=AStartAt;
  1421. Result:=-1;
  1422. If AExact then
  1423. while (I<Count) and (Result=-1) do
  1424. If Items[i].ClassType=AClass then
  1425. Result:=I
  1426. else
  1427. Inc(I)
  1428. else
  1429. while (I<Count) and (Result=-1) do
  1430. If Items[i].InheritsFrom(AClass) then
  1431. Result:=I
  1432. else
  1433. Inc(I);
  1434. end;
  1435. procedure TFPHashObjectList.Pack;
  1436. begin
  1437. FHashList.Pack;
  1438. end;
  1439. procedure TFPHashObjectList.ShowStatistics;
  1440. begin
  1441. FHashList.ShowStatistics;
  1442. end;
  1443. procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListCallback;arg:pointer);
  1444. begin
  1445. FHashList.ForEachCall(TListCallBack(proc2call),arg);
  1446. end;
  1447. procedure TFPHashObjectList.ForEachCall(proc2call:TObjectListStaticCallback;arg:pointer);
  1448. begin
  1449. FHashList.ForEachCall(TListStaticCallBack(proc2call),arg);
  1450. end;
  1451. {****************************************************************************
  1452. TLinkedListItem
  1453. ****************************************************************************}
  1454. constructor TLinkedListItem.Create;
  1455. begin
  1456. Previous:=nil;
  1457. Next:=nil;
  1458. end;
  1459. destructor TLinkedListItem.Destroy;
  1460. begin
  1461. end;
  1462. function TLinkedListItem.GetCopy:TLinkedListItem;
  1463. var
  1464. p : TLinkedListItem;
  1465. l : integer;
  1466. begin
  1467. p:=TLinkedListItemClass(ClassType).Create;
  1468. l:=InstanceSize;
  1469. Move(pointer(self)^,pointer(p)^,l);
  1470. Result:=p;
  1471. end;
  1472. {****************************************************************************
  1473. TLinkedList
  1474. ****************************************************************************}
  1475. constructor TLinkedList.Create;
  1476. begin
  1477. FFirst:=nil;
  1478. Flast:=nil;
  1479. FCount:=0;
  1480. FNoClear:=False;
  1481. end;
  1482. destructor TLinkedList.destroy;
  1483. begin
  1484. if not FNoClear then
  1485. Clear;
  1486. end;
  1487. function TLinkedList.empty:boolean;
  1488. begin
  1489. Empty:=(FFirst=nil);
  1490. end;
  1491. procedure TLinkedList.Insert(Item:TLinkedListItem);
  1492. begin
  1493. if FFirst=nil then
  1494. begin
  1495. FLast:=Item;
  1496. Item.Previous:=nil;
  1497. Item.Next:=nil;
  1498. end
  1499. else
  1500. begin
  1501. FFirst.Previous:=Item;
  1502. Item.Previous:=nil;
  1503. Item.Next:=FFirst;
  1504. end;
  1505. FFirst:=Item;
  1506. inc(FCount);
  1507. end;
  1508. procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
  1509. begin
  1510. Item.Previous:=Loc.Previous;
  1511. Item.Next:=Loc;
  1512. Loc.Previous:=Item;
  1513. if assigned(Item.Previous) then
  1514. Item.Previous.Next:=Item
  1515. else
  1516. { if we've no next item, we've to adjust FFist }
  1517. FFirst:=Item;
  1518. inc(FCount);
  1519. end;
  1520. procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
  1521. begin
  1522. Item.Next:=Loc.Next;
  1523. Loc.Next:=Item;
  1524. Item.Previous:=Loc;
  1525. if assigned(Item.Next) then
  1526. Item.Next.Previous:=Item
  1527. else
  1528. { if we've no next item, we've to adjust FLast }
  1529. FLast:=Item;
  1530. inc(FCount);
  1531. end;
  1532. procedure TLinkedList.Concat(Item:TLinkedListItem);
  1533. begin
  1534. if FFirst=nil then
  1535. begin
  1536. FFirst:=Item;
  1537. Item.Previous:=nil;
  1538. Item.Next:=nil;
  1539. end
  1540. else
  1541. begin
  1542. Flast.Next:=Item;
  1543. Item.Previous:=Flast;
  1544. Item.Next:=nil;
  1545. end;
  1546. Flast:=Item;
  1547. inc(FCount);
  1548. end;
  1549. procedure TLinkedList.remove(Item:TLinkedListItem);
  1550. begin
  1551. if Item=nil then
  1552. exit;
  1553. if (FFirst=Item) and (Flast=Item) then
  1554. begin
  1555. FFirst:=nil;
  1556. Flast:=nil;
  1557. end
  1558. else if FFirst=Item then
  1559. begin
  1560. FFirst:=Item.Next;
  1561. if assigned(FFirst) then
  1562. FFirst.Previous:=nil;
  1563. end
  1564. else if Flast=Item then
  1565. begin
  1566. Flast:=Flast.Previous;
  1567. if assigned(Flast) then
  1568. Flast.Next:=nil;
  1569. end
  1570. else
  1571. begin
  1572. Item.Previous.Next:=Item.Next;
  1573. Item.Next.Previous:=Item.Previous;
  1574. end;
  1575. Item.Next:=nil;
  1576. Item.Previous:=nil;
  1577. dec(FCount);
  1578. end;
  1579. procedure TLinkedList.clear;
  1580. var
  1581. NewNode : TLinkedListItem;
  1582. begin
  1583. NewNode:=FFirst;
  1584. while assigned(NewNode) do
  1585. begin
  1586. FFirst:=NewNode.Next;
  1587. NewNode.Free;
  1588. NewNode:=FFirst;
  1589. end;
  1590. FLast:=nil;
  1591. FFirst:=nil;
  1592. FCount:=0;
  1593. end;
  1594. function TLinkedList.GetFirst:TLinkedListItem;
  1595. begin
  1596. if FFirst=nil then
  1597. GetFirst:=nil
  1598. else
  1599. begin
  1600. GetFirst:=FFirst;
  1601. if FFirst=FLast then
  1602. FLast:=nil;
  1603. FFirst:=FFirst.Next;
  1604. dec(FCount);
  1605. end;
  1606. end;
  1607. function TLinkedList.GetLast:TLinkedListItem;
  1608. begin
  1609. if FLast=nil then
  1610. Getlast:=nil
  1611. else
  1612. begin
  1613. Getlast:=FLast;
  1614. if FLast=FFirst then
  1615. FFirst:=nil;
  1616. FLast:=FLast.Previous;
  1617. dec(FCount);
  1618. end;
  1619. end;
  1620. procedure TLinkedList.insertList(p : TLinkedList);
  1621. begin
  1622. { empty List ? }
  1623. if (p.FFirst=nil) then
  1624. exit;
  1625. p.Flast.Next:=FFirst;
  1626. { we have a double Linked List }
  1627. if assigned(FFirst) then
  1628. FFirst.Previous:=p.Flast;
  1629. FFirst:=p.FFirst;
  1630. if (FLast=nil) then
  1631. Flast:=p.Flast;
  1632. inc(FCount,p.FCount);
  1633. { p becomes empty }
  1634. p.FFirst:=nil;
  1635. p.Flast:=nil;
  1636. p.FCount:=0;
  1637. end;
  1638. procedure TLinkedList.insertListBefore(Item:TLinkedListItem;p : TLinkedList);
  1639. begin
  1640. { empty List ? }
  1641. if (p.FFirst=nil) then
  1642. exit;
  1643. if (Item=nil) then
  1644. begin
  1645. { Insert at begin }
  1646. InsertList(p);
  1647. exit;
  1648. end
  1649. else
  1650. begin
  1651. p.FLast.Next:=Item;
  1652. p.FFirst.Previous:=Item.Previous;
  1653. if assigned(Item.Previous) then
  1654. Item.Previous.Next:=p.FFirst
  1655. else
  1656. FFirst:=p.FFirst;
  1657. Item.Previous:=p.FLast;
  1658. inc(FCount,p.FCount);
  1659. end;
  1660. { p becomes empty }
  1661. p.FFirst:=nil;
  1662. p.Flast:=nil;
  1663. p.FCount:=0;
  1664. end;
  1665. procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  1666. begin
  1667. { empty List ? }
  1668. if (p.FFirst=nil) then
  1669. exit;
  1670. if (Item=nil) then
  1671. begin
  1672. { Insert at begin }
  1673. InsertList(p);
  1674. exit;
  1675. end
  1676. else
  1677. begin
  1678. p.FFirst.Previous:=Item;
  1679. p.FLast.Next:=Item.Next;
  1680. if assigned(Item.Next) then
  1681. Item.Next.Previous:=p.FLast
  1682. else
  1683. FLast:=p.FLast;
  1684. Item.Next:=p.FFirst;
  1685. inc(FCount,p.FCount);
  1686. end;
  1687. { p becomes empty }
  1688. p.FFirst:=nil;
  1689. p.Flast:=nil;
  1690. p.FCount:=0;
  1691. end;
  1692. procedure TLinkedList.concatList(p : TLinkedList);
  1693. begin
  1694. if (p.FFirst=nil) then
  1695. exit;
  1696. if FFirst=nil then
  1697. FFirst:=p.FFirst
  1698. else
  1699. begin
  1700. FLast.Next:=p.FFirst;
  1701. p.FFirst.Previous:=Flast;
  1702. end;
  1703. Flast:=p.Flast;
  1704. inc(FCount,p.FCount);
  1705. { make p empty }
  1706. p.Flast:=nil;
  1707. p.FFirst:=nil;
  1708. p.FCount:=0;
  1709. end;
  1710. procedure TLinkedList.insertListcopy(p : TLinkedList);
  1711. var
  1712. NewNode,NewNode2 : TLinkedListItem;
  1713. begin
  1714. NewNode:=p.First;
  1715. while assigned(NewNode) do
  1716. begin
  1717. NewNode2:=NewNode.Getcopy;
  1718. if assigned(NewNode2) then
  1719. Insert(NewNode2);
  1720. NewNode:=NewNode.Next;
  1721. end;
  1722. end;
  1723. procedure TLinkedList.concatListcopy(p : TLinkedList);
  1724. var
  1725. NewNode,NewNode2 : TLinkedListItem;
  1726. begin
  1727. NewNode:=p.First;
  1728. while assigned(NewNode) do
  1729. begin
  1730. NewNode2:=NewNode.Getcopy;
  1731. if assigned(NewNode2) then
  1732. Concat(NewNode2);
  1733. NewNode:=NewNode.Next;
  1734. end;
  1735. end;
  1736. {****************************************************************************
  1737. TStringListItem
  1738. ****************************************************************************}
  1739. constructor TStringListItem.Create(const s:string);
  1740. begin
  1741. inherited Create;
  1742. FPStr:=stringdup(s);
  1743. end;
  1744. destructor TStringListItem.Destroy;
  1745. begin
  1746. stringdispose(FPStr);
  1747. end;
  1748. function TStringListItem.Str:string;
  1749. begin
  1750. Str:=FPStr^;
  1751. end;
  1752. function TStringListItem.GetCopy:TLinkedListItem;
  1753. begin
  1754. Result:=(inherited GetCopy);
  1755. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  1756. end;
  1757. {****************************************************************************
  1758. TSTRINGList
  1759. ****************************************************************************}
  1760. constructor tstringList.Create;
  1761. begin
  1762. inherited Create;
  1763. FDoubles:=true;
  1764. end;
  1765. constructor tstringList.Create_no_double;
  1766. begin
  1767. inherited Create;
  1768. FDoubles:=false;
  1769. end;
  1770. procedure tstringList.insert(const s : string);
  1771. begin
  1772. if (s='') or
  1773. ((not FDoubles) and (find(s)<>nil)) then
  1774. exit;
  1775. inherited insert(tstringListItem.create(s));
  1776. end;
  1777. procedure tstringList.concat(const s : string);
  1778. begin
  1779. if (s='') or
  1780. ((not FDoubles) and (find(s)<>nil)) then
  1781. exit;
  1782. inherited concat(tstringListItem.create(s));
  1783. end;
  1784. procedure tstringList.remove(const s : string);
  1785. var
  1786. p : tstringListItem;
  1787. begin
  1788. if s='' then
  1789. exit;
  1790. p:=find(s);
  1791. if assigned(p) then
  1792. begin
  1793. inherited Remove(p);
  1794. p.Free;
  1795. end;
  1796. end;
  1797. function tstringList.GetFirst : string;
  1798. var
  1799. p : tstringListItem;
  1800. begin
  1801. p:=tstringListItem(inherited GetFirst);
  1802. if p=nil then
  1803. GetFirst:=''
  1804. else
  1805. begin
  1806. GetFirst:=p.FPStr^;
  1807. p.free;
  1808. end;
  1809. end;
  1810. function tstringList.Getlast : string;
  1811. var
  1812. p : tstringListItem;
  1813. begin
  1814. p:=tstringListItem(inherited Getlast);
  1815. if p=nil then
  1816. Getlast:=''
  1817. else
  1818. begin
  1819. Getlast:=p.FPStr^;
  1820. p.free;
  1821. end;
  1822. end;
  1823. function tstringList.FindCase(const s:string):TstringListItem;
  1824. var
  1825. NewNode : tstringListItem;
  1826. begin
  1827. result:=nil;
  1828. if s='' then
  1829. exit;
  1830. NewNode:=tstringListItem(FFirst);
  1831. while assigned(NewNode) do
  1832. begin
  1833. if NewNode.FPStr^=s then
  1834. begin
  1835. result:=NewNode;
  1836. exit;
  1837. end;
  1838. NewNode:=tstringListItem(NewNode.Next);
  1839. end;
  1840. end;
  1841. function tstringList.Find(const s:string):TstringListItem;
  1842. var
  1843. NewNode : tstringListItem;
  1844. ups : string;
  1845. begin
  1846. result:=nil;
  1847. if s='' then
  1848. exit;
  1849. ups:=upper(s);
  1850. NewNode:=tstringListItem(FFirst);
  1851. while assigned(NewNode) do
  1852. begin
  1853. if upper(NewNode.FPStr^)=ups then
  1854. begin
  1855. result:=NewNode;
  1856. exit;
  1857. end;
  1858. NewNode:=tstringListItem(NewNode.Next);
  1859. end;
  1860. end;
  1861. procedure TStringList.InsertItem(item:TStringListItem);
  1862. begin
  1863. inherited Insert(item);
  1864. end;
  1865. procedure TStringList.ConcatItem(item:TStringListItem);
  1866. begin
  1867. inherited Concat(item);
  1868. end;
  1869. procedure TStringList.readstream(f:TCStream);
  1870. const
  1871. BufSize = 16384;
  1872. var
  1873. Hsp,
  1874. p,maxp,
  1875. Buf : PChar;
  1876. Prev : Char;
  1877. HsPos,
  1878. ReadLen,
  1879. BufPos,
  1880. BufEnd : Longint;
  1881. hs : string;
  1882. procedure ReadBuf;
  1883. begin
  1884. if BufPos<BufEnd then
  1885. begin
  1886. Move(Buf[BufPos],Buf[0],BufEnd-BufPos);
  1887. Dec(BufEnd,BufPos);
  1888. BufPos:=0;
  1889. end;
  1890. ReadLen:=f.Read(buf[BufEnd],BufSize-BufEnd);
  1891. inc(BufEnd,ReadLen);
  1892. end;
  1893. begin
  1894. Getmem(Buf,Bufsize);
  1895. BufPos:=0;
  1896. BufEnd:=0;
  1897. HsPos:=1;
  1898. ReadBuf;
  1899. repeat
  1900. hsp:=@hs[hsPos];
  1901. p:=@Buf[BufPos];
  1902. maxp:=@Buf[BufEnd];
  1903. while (p<maxp) and not(P^ in [#10,#13]) do
  1904. begin
  1905. hsp^:=p^;
  1906. inc(p);
  1907. if hsp-@hs[1]<255 then
  1908. inc(hsp);
  1909. end;
  1910. inc(BufPos,maxp-p);
  1911. inc(HsPos,maxp-p);
  1912. prev:=p^;
  1913. inc(BufPos);
  1914. { no system uses #10#13 as line seperator (#10 = *nix, #13 = Mac, }
  1915. { #13#10 = Dos), so if we've got #10, we can safely exit }
  1916. if (prev<>#10) then
  1917. begin
  1918. if (BufPos>=BufEnd) then
  1919. begin
  1920. ReadBuf;
  1921. if BufPos>=BufEnd then
  1922. break;
  1923. end;
  1924. { is there also a #10 after it? }
  1925. if prev=#13 then
  1926. begin
  1927. if (Buf[BufPos]=#10) then
  1928. inc(BufPos);
  1929. prev:=#10;
  1930. end;
  1931. end;
  1932. if prev=#10 then
  1933. begin
  1934. hs[0]:=char(hsp-@hs[1]);
  1935. Concat(hs);
  1936. HsPos:=1;
  1937. end;
  1938. until BufPos>=BufEnd;
  1939. hs[0]:=char(hsp-@hs[1]);
  1940. Concat(hs);
  1941. freemem(buf);
  1942. end;
  1943. procedure TStringList.writestream(f:TCStream);
  1944. var
  1945. Node : TStringListItem;
  1946. LineEnd : string[2];
  1947. begin
  1948. Case DefaultTextLineBreakStyle Of
  1949. tlbsLF: LineEnd := #10;
  1950. tlbsCRLF: LineEnd := #13#10;
  1951. tlbsCR: LineEnd := #13;
  1952. End;
  1953. Node:=tstringListItem(FFirst);
  1954. while assigned(Node) do
  1955. begin
  1956. f.Write(Node.FPStr^[1],Length(Node.FPStr^));
  1957. f.Write(LineEnd[1],length(LineEnd));
  1958. Node:=tstringListItem(Node.Next);
  1959. end;
  1960. end;
  1961. {****************************************************************************
  1962. TNamedIndexItem
  1963. ****************************************************************************}
  1964. constructor TNamedIndexItem.Create;
  1965. begin
  1966. { index }
  1967. Findexnr:=-1;
  1968. FindexNext:=nil;
  1969. { dictionary }
  1970. Fleft:=nil;
  1971. Fright:=nil;
  1972. FName:=nil;
  1973. Fspeedvalue:=cardinal($ffffffff);
  1974. end;
  1975. constructor TNamedIndexItem.Createname(const n:string);
  1976. begin
  1977. { index }
  1978. Findexnr:=-1;
  1979. FindexNext:=nil;
  1980. { dictionary }
  1981. Fleft:=nil;
  1982. Fright:=nil;
  1983. fspeedvalue:=getspeedvalue(n);
  1984. {$ifdef compress}
  1985. FName:=stringdup(minilzw_encode(n));
  1986. {$else}
  1987. FName:=stringdup(n);
  1988. {$endif}
  1989. end;
  1990. destructor TNamedIndexItem.destroy;
  1991. begin
  1992. stringdispose(FName);
  1993. end;
  1994. procedure TNamedIndexItem.setname(const n:string);
  1995. begin
  1996. if assigned(FName) then
  1997. stringdispose(FName);
  1998. fspeedvalue:=getspeedvalue(n);
  1999. {$ifdef compress}
  2000. FName:=stringdup(minilzw_encode(n));
  2001. {$else}
  2002. FName:=stringdup(n);
  2003. {$endif}
  2004. end;
  2005. function TNamedIndexItem.GetName:string;
  2006. begin
  2007. if assigned(FName) then
  2008. {$ifdef compress}
  2009. Getname:=minilzw_decode(FName^)
  2010. {$else}
  2011. Getname:=FName^
  2012. {$endif}
  2013. else
  2014. Getname:='';
  2015. end;
  2016. {****************************************************************************
  2017. TDICTIONARY
  2018. ****************************************************************************}
  2019. constructor Tdictionary.Create;
  2020. begin
  2021. FRoot:=nil;
  2022. FHashArray:=nil;
  2023. noclear:=false;
  2024. delete_doubles:=false;
  2025. end;
  2026. procedure Tdictionary.usehash;
  2027. begin
  2028. if not(assigned(FRoot)) and
  2029. not(assigned(FHashArray)) then
  2030. begin
  2031. New(FHashArray);
  2032. fillchar(FHashArray^,sizeof(FHashArray^),0);
  2033. end;
  2034. end;
  2035. function counttree(p: tnamedindexitem): longint;
  2036. begin
  2037. counttree:=0;
  2038. if not assigned(p) then
  2039. exit;
  2040. result := 1;
  2041. inc(result,counttree(p.fleft));
  2042. inc(result,counttree(p.fright));
  2043. end;
  2044. destructor Tdictionary.destroy;
  2045. begin
  2046. if not noclear then
  2047. clear;
  2048. if assigned(FHashArray) then
  2049. begin
  2050. dispose(FHashArray);
  2051. end;
  2052. end;
  2053. procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
  2054. begin
  2055. if assigned(obj.Fleft) then
  2056. cleartree(obj.FLeft);
  2057. if assigned(obj.FRight) then
  2058. cleartree(obj.FRight);
  2059. obj.free;
  2060. obj:=nil;
  2061. end;
  2062. procedure Tdictionary.clear;
  2063. var
  2064. w : integer;
  2065. begin
  2066. if assigned(FRoot) then
  2067. cleartree(FRoot);
  2068. if assigned(FHashArray) then
  2069. for w:= low(FHashArray^) to high(FHashArray^) do
  2070. if assigned(FHashArray^[w]) then
  2071. cleartree(FHashArray^[w]);
  2072. end;
  2073. function Tdictionary.delete(const s:string):TNamedIndexItem;
  2074. var
  2075. p,SpeedValue : cardinal;
  2076. n : TNamedIndexItem;
  2077. {$ifdef compress}
  2078. senc:string;
  2079. {$else}
  2080. senc:string absolute s;
  2081. {$endif}
  2082. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  2083. begin
  2084. while root.FRight<>nil do
  2085. root:=root.FRight;
  2086. root.FRight:=Atree;
  2087. end;
  2088. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  2089. type
  2090. leftright=(left,right);
  2091. var
  2092. lr : leftright;
  2093. oldroot : TNamedIndexItem;
  2094. begin
  2095. oldroot:=nil;
  2096. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  2097. begin
  2098. oldroot:=root;
  2099. if SpeedValue<root.SpeedValue then
  2100. begin
  2101. root:=root.FRight;
  2102. lr:=right;
  2103. end
  2104. else
  2105. begin
  2106. root:=root.FLeft;
  2107. lr:=left;
  2108. end;
  2109. end;
  2110. while (root<>nil) and (root.FName^<>senc) do
  2111. begin
  2112. oldroot:=root;
  2113. if senc<root.FName^ then
  2114. begin
  2115. root:=root.FRight;
  2116. lr:=right;
  2117. end
  2118. else
  2119. begin
  2120. root:=root.FLeft;
  2121. lr:=left;
  2122. end;
  2123. end;
  2124. if root<>nil then
  2125. begin
  2126. dec(FCount);
  2127. if root.FLeft<>nil then
  2128. begin
  2129. { Now the Node pointing to root must point to the left
  2130. subtree of root. The right subtree of root must be
  2131. connected to the right bottom of the left subtree.}
  2132. if lr=left then
  2133. oldroot.FLeft:=root.FLeft
  2134. else
  2135. oldroot.FRight:=root.FLeft;
  2136. if root.FRight<>nil then
  2137. insert_right_bottom(root.FLeft,root.FRight);
  2138. end
  2139. else
  2140. begin
  2141. { There is no left subtree. So we can just replace the Node to
  2142. delete with the right subtree.}
  2143. if lr=left then
  2144. oldroot.FLeft:=root.FRight
  2145. else
  2146. oldroot.FRight:=root.FRight;
  2147. end;
  2148. end;
  2149. delete_from_tree:=root;
  2150. end;
  2151. begin
  2152. {$ifdef compress}
  2153. senc:=minilzw_encode(s);
  2154. {$endif}
  2155. SpeedValue:=GetSpeedValue(s);
  2156. n:=FRoot;
  2157. if assigned(FHashArray) then
  2158. begin
  2159. { First, check if the Node to delete directly located under
  2160. the hasharray.}
  2161. p:=SpeedValue mod hasharraysize;
  2162. n:=FHashArray^[p];
  2163. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  2164. (n.FName^=senc) then
  2165. begin
  2166. { The Node to delete is directly located under the
  2167. hasharray. Make the hasharray point to the left
  2168. subtree of the Node and place the right subtree on
  2169. the right-bottom of the left subtree.}
  2170. if n.FLeft<>nil then
  2171. begin
  2172. FHashArray^[p]:=n.FLeft;
  2173. if n.FRight<>nil then
  2174. insert_right_bottom(n.FLeft,n.FRight);
  2175. end
  2176. else
  2177. FHashArray^[p]:=n.FRight;
  2178. delete:=n;
  2179. dec(FCount);
  2180. exit;
  2181. end;
  2182. end
  2183. else
  2184. begin
  2185. { First check if the Node to delete is the root.}
  2186. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  2187. (n.FName^=senc) then
  2188. begin
  2189. if n.FLeft<>nil then
  2190. begin
  2191. FRoot:=n.FLeft;
  2192. if n.FRight<>nil then
  2193. insert_right_bottom(n.FLeft,n.FRight);
  2194. end
  2195. else
  2196. FRoot:=n.FRight;
  2197. delete:=n;
  2198. dec(FCount);
  2199. exit;
  2200. end;
  2201. end;
  2202. delete:=delete_from_tree(n);
  2203. end;
  2204. function Tdictionary.empty:boolean;
  2205. var
  2206. w : integer;
  2207. begin
  2208. if assigned(FHashArray) then
  2209. begin
  2210. empty:=false;
  2211. for w:=low(FHashArray^) to high(FHashArray^) do
  2212. if assigned(FHashArray^[w]) then
  2213. exit;
  2214. empty:=true;
  2215. end
  2216. else
  2217. empty:=(FRoot=nil);
  2218. end;
  2219. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
  2220. procedure a(p:TNamedIndexItem;arg:pointer);
  2221. begin
  2222. proc2call(p,arg);
  2223. if assigned(p.FLeft) then
  2224. a(p.FLeft,arg);
  2225. if assigned(p.FRight) then
  2226. a(p.FRight,arg);
  2227. end;
  2228. var
  2229. i : integer;
  2230. begin
  2231. if assigned(FHashArray) then
  2232. begin
  2233. for i:=low(FHashArray^) to high(FHashArray^) do
  2234. if assigned(FHashArray^[i]) then
  2235. a(FHashArray^[i],arg);
  2236. end
  2237. else
  2238. if assigned(FRoot) then
  2239. a(FRoot,arg);
  2240. end;
  2241. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  2242. procedure a(p:TNamedIndexItem;arg:pointer);
  2243. begin
  2244. proc2call(p,arg);
  2245. if assigned(p.FLeft) then
  2246. a(p.FLeft,arg);
  2247. if assigned(p.FRight) then
  2248. a(p.FRight,arg);
  2249. end;
  2250. var
  2251. i : integer;
  2252. begin
  2253. if assigned(FHashArray) then
  2254. begin
  2255. for i:=low(FHashArray^) to high(FHashArray^) do
  2256. if assigned(FHashArray^[i]) then
  2257. a(FHashArray^[i],arg);
  2258. end
  2259. else
  2260. if assigned(FRoot) then
  2261. a(FRoot,arg);
  2262. end;
  2263. function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
  2264. var
  2265. hp : TNamedIndexItem;
  2266. begin
  2267. hp:=nil;
  2268. Replace:=false;
  2269. { must be the same name and hash }
  2270. if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
  2271. (oldobj.FName^<>newobj.FName^) then
  2272. exit;
  2273. { copy tree info }
  2274. newobj.FLeft:=oldobj.FLeft;
  2275. newobj.FRight:=oldobj.FRight;
  2276. { update treeroot }
  2277. if assigned(FHashArray) then
  2278. begin
  2279. hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
  2280. if hp=oldobj then
  2281. begin
  2282. FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
  2283. hp:=nil;
  2284. end;
  2285. end
  2286. else
  2287. begin
  2288. hp:=FRoot;
  2289. if hp=oldobj then
  2290. begin
  2291. FRoot:=newobj;
  2292. hp:=nil;
  2293. end;
  2294. end;
  2295. { update parent entry }
  2296. while assigned(hp) do
  2297. begin
  2298. { is the node to replace the left or right, then
  2299. update this node and stop }
  2300. if hp.FLeft=oldobj then
  2301. begin
  2302. hp.FLeft:=newobj;
  2303. break;
  2304. end;
  2305. if hp.FRight=oldobj then
  2306. begin
  2307. hp.FRight:=newobj;
  2308. break;
  2309. end;
  2310. { First check SpeedValue, to allow a fast insert }
  2311. if hp.SpeedValue>oldobj.SpeedValue then
  2312. hp:=hp.FRight
  2313. else
  2314. if hp.SpeedValue<oldobj.SpeedValue then
  2315. hp:=hp.FLeft
  2316. else
  2317. begin
  2318. if (hp.FName^=oldobj.FName^) then
  2319. begin
  2320. { this can never happend, return error }
  2321. exit;
  2322. end
  2323. else
  2324. if oldobj.FName^>hp.FName^ then
  2325. hp:=hp.FLeft
  2326. else
  2327. hp:=hp.FRight;
  2328. end;
  2329. end;
  2330. Replace:=true;
  2331. end;
  2332. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  2333. begin
  2334. inc(FCount);
  2335. if assigned(FHashArray) then
  2336. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  2337. else
  2338. insert:=insertNode(obj,FRoot);
  2339. end;
  2340. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  2341. begin
  2342. if currNode=nil then
  2343. begin
  2344. currNode:=NewNode;
  2345. insertNode:=NewNode;
  2346. end
  2347. { First check SpeedValue, to allow a fast insert }
  2348. else
  2349. if currNode.SpeedValue>NewNode.SpeedValue then
  2350. insertNode:=insertNode(NewNode,currNode.FRight)
  2351. else
  2352. if currNode.SpeedValue<NewNode.SpeedValue then
  2353. insertNode:=insertNode(NewNode,currNode.FLeft)
  2354. else
  2355. begin
  2356. if currNode.FName^>NewNode.FName^ then
  2357. insertNode:=insertNode(NewNode,currNode.FRight)
  2358. else
  2359. if currNode.FName^<NewNode.FName^ then
  2360. insertNode:=insertNode(NewNode,currNode.FLeft)
  2361. else
  2362. begin
  2363. if (delete_doubles) and
  2364. assigned(currNode) then
  2365. begin
  2366. NewNode.FLeft:=currNode.FLeft;
  2367. NewNode.FRight:=currNode.FRight;
  2368. if delete_doubles then
  2369. begin
  2370. currnode.FLeft:=nil;
  2371. currnode.FRight:=nil;
  2372. currnode.free;
  2373. end;
  2374. currNode:=NewNode;
  2375. insertNode:=NewNode;
  2376. end
  2377. else
  2378. insertNode:=currNode;
  2379. end;
  2380. end;
  2381. end;
  2382. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  2383. begin
  2384. if assigned(currtree) then
  2385. begin
  2386. inserttree(currtree.FLeft,currroot);
  2387. inserttree(currtree.FRight,currroot);
  2388. currtree.FRight:=nil;
  2389. currtree.FLeft:=nil;
  2390. insertNode(currtree,currroot);
  2391. end;
  2392. end;
  2393. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  2394. var
  2395. spdval : cardinal;
  2396. lasthp,
  2397. hp,hp2,hp3 : TNamedIndexItem;
  2398. {$ifdef compress}
  2399. oldsenc,newsenc:string;
  2400. {$else}
  2401. oldsenc:string absolute olds;
  2402. newsenc:string absolute news;
  2403. {$endif}
  2404. begin
  2405. {$ifdef compress}
  2406. oldsenc:=minilzw_encode(olds);
  2407. newsenc:=minilzw_encode(news);
  2408. {$endif}
  2409. spdval:=GetSpeedValue(olds);
  2410. if assigned(FHashArray) then
  2411. hp:=FHashArray^[spdval mod hasharraysize]
  2412. else
  2413. hp:=FRoot;
  2414. lasthp:=nil;
  2415. while assigned(hp) do
  2416. begin
  2417. if spdval>hp.SpeedValue then
  2418. begin
  2419. lasthp:=hp;
  2420. hp:=hp.FLeft
  2421. end
  2422. else
  2423. if spdval<hp.SpeedValue then
  2424. begin
  2425. lasthp:=hp;
  2426. hp:=hp.FRight
  2427. end
  2428. else
  2429. begin
  2430. if (hp.FName^=oldsenc) then
  2431. begin
  2432. { Get in hp2 the replacer for the root or hasharr }
  2433. hp2:=hp.FLeft;
  2434. hp3:=hp.FRight;
  2435. if not assigned(hp2) then
  2436. begin
  2437. hp2:=hp.FRight;
  2438. hp3:=hp.FLeft;
  2439. end;
  2440. { remove entry from the tree }
  2441. if assigned(lasthp) then
  2442. begin
  2443. if lasthp.FLeft=hp then
  2444. lasthp.FLeft:=hp2
  2445. else
  2446. lasthp.FRight:=hp2;
  2447. end
  2448. else
  2449. begin
  2450. if assigned(FHashArray) then
  2451. FHashArray^[spdval mod hasharraysize]:=hp2
  2452. else
  2453. FRoot:=hp2;
  2454. end;
  2455. { reinsert the hp3 in the tree from hp2 }
  2456. inserttree(hp3,hp2);
  2457. { reset Node with New values }
  2458. hp.FLeft:=nil;
  2459. hp.FRight:=nil;
  2460. stringdispose(hp.FName);
  2461. hp.FName:=stringdup(newsenc);
  2462. hp.FSpeedValue:=GetSpeedValue(news);
  2463. { reinsert }
  2464. if assigned(FHashArray) then
  2465. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  2466. else
  2467. rename:=insertNode(hp,FRoot);
  2468. exit;
  2469. end
  2470. else
  2471. if oldsenc>hp.FName^ then
  2472. begin
  2473. lasthp:=hp;
  2474. hp:=hp.FLeft
  2475. end
  2476. else
  2477. begin
  2478. lasthp:=hp;
  2479. hp:=hp.FRight;
  2480. end;
  2481. end;
  2482. end;
  2483. result := nil;
  2484. end;
  2485. function Tdictionary.search(const s:string):TNamedIndexItem;
  2486. begin
  2487. search:=speedsearch(s,getspeedvalue(s));
  2488. end;
  2489. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  2490. var
  2491. NewNode:TNamedIndexItem;
  2492. {$ifdef compress}
  2493. decn:string;
  2494. {$endif}
  2495. begin
  2496. if assigned(FHashArray) then
  2497. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  2498. else
  2499. NewNode:=FRoot;
  2500. while assigned(NewNode) do
  2501. begin
  2502. if SpeedValue>NewNode.SpeedValue then
  2503. NewNode:=NewNode.FLeft
  2504. else
  2505. if SpeedValue<NewNode.SpeedValue then
  2506. NewNode:=NewNode.FRight
  2507. else
  2508. begin
  2509. {$ifdef compress}
  2510. decn:=minilzw_decode(newnode.fname^);
  2511. if (decn=s) then
  2512. begin
  2513. speedsearch:=NewNode;
  2514. exit;
  2515. end
  2516. else
  2517. if s>decn then
  2518. NewNode:=NewNode.FLeft
  2519. else
  2520. NewNode:=NewNode.FRight;
  2521. {$else}
  2522. if (NewNode.FName^=s) then
  2523. begin
  2524. speedsearch:=NewNode;
  2525. exit;
  2526. end
  2527. else
  2528. if s>NewNode.FName^ then
  2529. NewNode:=NewNode.FLeft
  2530. else
  2531. NewNode:=NewNode.FRight;
  2532. {$endif}
  2533. end;
  2534. end;
  2535. speedsearch:=nil;
  2536. end;
  2537. {****************************************************************************
  2538. tindexarray
  2539. ****************************************************************************}
  2540. constructor tindexarray.create(Agrowsize:integer);
  2541. begin
  2542. growsize:=Agrowsize;
  2543. size:=0;
  2544. count:=0;
  2545. data:=nil;
  2546. First:=nil;
  2547. noclear:=false;
  2548. end;
  2549. destructor tindexarray.destroy;
  2550. begin
  2551. if assigned(data) then
  2552. begin
  2553. if not noclear then
  2554. clear;
  2555. freemem(data);
  2556. data:=nil;
  2557. end;
  2558. end;
  2559. function tindexarray.search(nr:integer):TNamedIndexItem;
  2560. begin
  2561. if nr<=count then
  2562. search:=data^[nr]
  2563. else
  2564. search:=nil;
  2565. end;
  2566. procedure tindexarray.clear;
  2567. var
  2568. i : integer;
  2569. begin
  2570. for i:=1 to count do
  2571. if assigned(data^[i]) then
  2572. begin
  2573. data^[i].free;
  2574. data^[i]:=nil;
  2575. end;
  2576. count:=0;
  2577. First:=nil;
  2578. end;
  2579. procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
  2580. var
  2581. i : integer;
  2582. begin
  2583. for i:=1 to count do
  2584. if assigned(data^[i]) then
  2585. proc2call(data^[i],arg);
  2586. end;
  2587. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  2588. var
  2589. i : integer;
  2590. begin
  2591. for i:=1 to count do
  2592. if assigned(data^[i]) then
  2593. proc2call(data^[i],arg);
  2594. end;
  2595. procedure tindexarray.grow(gsize:integer);
  2596. var
  2597. osize : integer;
  2598. begin
  2599. osize:=size;
  2600. inc(size,gsize);
  2601. reallocmem(data,size*sizeof(pointer));
  2602. fillchar(data^[osize+1],gsize*sizeof(pointer),0);
  2603. end;
  2604. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  2605. var
  2606. i : integer;
  2607. begin
  2608. i:=p.Findexnr;
  2609. { update counter }
  2610. if i=count then
  2611. dec(count);
  2612. { update Linked List }
  2613. while (i>0) do
  2614. begin
  2615. dec(i);
  2616. if (i>0) and assigned(data^[i]) then
  2617. begin
  2618. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  2619. break;
  2620. end;
  2621. end;
  2622. if i=0 then
  2623. First:=p.FindexNext;
  2624. data^[p.FIndexnr]:=nil;
  2625. { clear entry }
  2626. p.FIndexnr:=-1;
  2627. p.FIndexNext:=nil;
  2628. end;
  2629. procedure tindexarray.delete(var p:TNamedIndexItem);
  2630. begin
  2631. deleteindex(p);
  2632. p.free;
  2633. p:=nil;
  2634. end;
  2635. procedure tindexarray.insert(p:TNamedIndexItem);
  2636. var
  2637. i : integer;
  2638. begin
  2639. if p.FIndexnr=-1 then
  2640. begin
  2641. inc(count);
  2642. p.FIndexnr:=count;
  2643. end;
  2644. if p.FIndexnr>count then
  2645. count:=p.FIndexnr;
  2646. if count>size then
  2647. grow(((count div growsize)+1)*growsize);
  2648. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  2649. data^[p.FIndexnr]:=p;
  2650. { update Linked List backward }
  2651. i:=p.FIndexnr;
  2652. while (i>0) do
  2653. begin
  2654. dec(i);
  2655. if (i>0) and assigned(data^[i]) then
  2656. begin
  2657. data^[i].FIndexNext:=p;
  2658. break;
  2659. end;
  2660. end;
  2661. if i=0 then
  2662. First:=p;
  2663. { update Linked List forward }
  2664. i:=p.FIndexnr;
  2665. while (i<=count) do
  2666. begin
  2667. inc(i);
  2668. if (i<=count) and assigned(data^[i]) then
  2669. begin
  2670. p.FIndexNext:=data^[i];
  2671. exit;
  2672. end;
  2673. end;
  2674. if i>count then
  2675. p.FIndexNext:=nil;
  2676. end;
  2677. procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
  2678. var
  2679. i : integer;
  2680. begin
  2681. newp.FIndexnr:=oldp.FIndexnr;
  2682. newp.FIndexNext:=oldp.FIndexNext;
  2683. data^[newp.FIndexnr]:=newp;
  2684. if First=oldp then
  2685. First:=newp;
  2686. { update Linked List backward }
  2687. i:=newp.FIndexnr;
  2688. while (i>0) do
  2689. begin
  2690. dec(i);
  2691. if (i>0) and assigned(data^[i]) then
  2692. begin
  2693. data^[i].FIndexNext:=newp;
  2694. break;
  2695. end;
  2696. end;
  2697. end;
  2698. {****************************************************************************
  2699. tdynamicarray
  2700. ****************************************************************************}
  2701. constructor tdynamicarray.create(Ablocksize:integer);
  2702. begin
  2703. FPosn:=0;
  2704. FPosnblock:=nil;
  2705. FFirstblock:=nil;
  2706. FLastblock:=nil;
  2707. Fblocksize:=Ablocksize;
  2708. grow;
  2709. end;
  2710. destructor tdynamicarray.destroy;
  2711. var
  2712. hp : pdynamicblock;
  2713. begin
  2714. while assigned(FFirstblock) do
  2715. begin
  2716. hp:=FFirstblock;
  2717. FFirstblock:=FFirstblock^.Next;
  2718. Freemem(hp);
  2719. end;
  2720. end;
  2721. function tdynamicarray.size:integer;
  2722. begin
  2723. if assigned(FLastblock) then
  2724. size:=FLastblock^.pos+FLastblock^.used
  2725. else
  2726. size:=0;
  2727. end;
  2728. procedure tdynamicarray.reset;
  2729. var
  2730. hp : pdynamicblock;
  2731. begin
  2732. while assigned(FFirstblock) do
  2733. begin
  2734. hp:=FFirstblock;
  2735. FFirstblock:=FFirstblock^.Next;
  2736. Freemem(hp);
  2737. end;
  2738. FPosn:=0;
  2739. FPosnblock:=nil;
  2740. FFirstblock:=nil;
  2741. FLastblock:=nil;
  2742. grow;
  2743. end;
  2744. procedure tdynamicarray.grow;
  2745. var
  2746. nblock : pdynamicblock;
  2747. begin
  2748. Getmem(nblock,blocksize+dynamicblockbasesize);
  2749. if not assigned(FFirstblock) then
  2750. begin
  2751. FFirstblock:=nblock;
  2752. FPosnblock:=nblock;
  2753. nblock^.pos:=0;
  2754. end
  2755. else
  2756. begin
  2757. FLastblock^.Next:=nblock;
  2758. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  2759. end;
  2760. nblock^.used:=0;
  2761. nblock^.Next:=nil;
  2762. fillchar(nblock^.data,blocksize,0);
  2763. FLastblock:=nblock;
  2764. end;
  2765. procedure tdynamicarray.align(i:integer);
  2766. var
  2767. j : integer;
  2768. begin
  2769. j:=(FPosn mod i);
  2770. if j<>0 then
  2771. begin
  2772. j:=i-j;
  2773. if FPosnblock^.used+j>blocksize then
  2774. begin
  2775. dec(j,blocksize-FPosnblock^.used);
  2776. FPosnblock^.used:=blocksize;
  2777. grow;
  2778. FPosnblock:=FLastblock;
  2779. end;
  2780. inc(FPosnblock^.used,j);
  2781. inc(FPosn,j);
  2782. end;
  2783. end;
  2784. procedure tdynamicarray.seek(i:integer);
  2785. begin
  2786. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  2787. begin
  2788. { set FPosnblock correct if the size is bigger then
  2789. the current block }
  2790. if FPosnblock^.pos>i then
  2791. FPosnblock:=FFirstblock;
  2792. while assigned(FPosnblock) do
  2793. begin
  2794. if FPosnblock^.pos+blocksize>i then
  2795. break;
  2796. FPosnblock:=FPosnblock^.Next;
  2797. end;
  2798. { not found ? then increase blocks }
  2799. if not assigned(FPosnblock) then
  2800. begin
  2801. repeat
  2802. { the current FLastblock is now also fully used }
  2803. FLastblock^.used:=blocksize;
  2804. grow;
  2805. FPosnblock:=FLastblock;
  2806. until FPosnblock^.pos+blocksize>=i;
  2807. end;
  2808. end;
  2809. FPosn:=i;
  2810. if FPosn mod blocksize>FPosnblock^.used then
  2811. FPosnblock^.used:=FPosn mod blocksize;
  2812. end;
  2813. procedure tdynamicarray.write(const d;len:integer);
  2814. var
  2815. p : pchar;
  2816. i,j : integer;
  2817. begin
  2818. p:=pchar(@d);
  2819. while (len>0) do
  2820. begin
  2821. i:=FPosn mod blocksize;
  2822. if i+len>=blocksize then
  2823. begin
  2824. j:=blocksize-i;
  2825. move(p^,FPosnblock^.data[i],j);
  2826. inc(p,j);
  2827. inc(FPosn,j);
  2828. dec(len,j);
  2829. FPosnblock^.used:=blocksize;
  2830. if assigned(FPosnblock^.Next) then
  2831. FPosnblock:=FPosnblock^.Next
  2832. else
  2833. begin
  2834. grow;
  2835. FPosnblock:=FLastblock;
  2836. end;
  2837. end
  2838. else
  2839. begin
  2840. move(p^,FPosnblock^.data[i],len);
  2841. inc(p,len);
  2842. inc(FPosn,len);
  2843. i:=FPosn mod blocksize;
  2844. if i>FPosnblock^.used then
  2845. FPosnblock^.used:=i;
  2846. len:=0;
  2847. end;
  2848. end;
  2849. end;
  2850. procedure tdynamicarray.writestr(const s:string);
  2851. begin
  2852. write(s[1],length(s));
  2853. end;
  2854. function tdynamicarray.read(var d;len:integer):integer;
  2855. var
  2856. p : pchar;
  2857. i,j,res : integer;
  2858. begin
  2859. res:=0;
  2860. p:=pchar(@d);
  2861. while (len>0) do
  2862. begin
  2863. i:=FPosn mod blocksize;
  2864. if i+len>=FPosnblock^.used then
  2865. begin
  2866. j:=FPosnblock^.used-i;
  2867. move(FPosnblock^.data[i],p^,j);
  2868. inc(p,j);
  2869. inc(FPosn,j);
  2870. inc(res,j);
  2871. dec(len,j);
  2872. if assigned(FPosnblock^.Next) then
  2873. FPosnblock:=FPosnblock^.Next
  2874. else
  2875. break;
  2876. end
  2877. else
  2878. begin
  2879. move(FPosnblock^.data[i],p^,len);
  2880. inc(p,len);
  2881. inc(FPosn,len);
  2882. inc(res,len);
  2883. len:=0;
  2884. end;
  2885. end;
  2886. read:=res;
  2887. end;
  2888. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  2889. var
  2890. i,left : integer;
  2891. begin
  2892. if maxlen=-1 then
  2893. maxlen:=maxlongint;
  2894. repeat
  2895. left:=blocksize-FPosnblock^.used;
  2896. if left>maxlen then
  2897. left:=maxlen;
  2898. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  2899. dec(maxlen,i);
  2900. inc(FPosnblock^.used,i);
  2901. if FPosnblock^.used=blocksize then
  2902. begin
  2903. if assigned(FPosnblock^.Next) then
  2904. FPosnblock:=FPosnblock^.Next
  2905. else
  2906. begin
  2907. grow;
  2908. FPosnblock:=FLastblock;
  2909. end;
  2910. end;
  2911. until (i<left) or (maxlen=0);
  2912. end;
  2913. procedure tdynamicarray.writestream(f:TCStream);
  2914. var
  2915. hp : pdynamicblock;
  2916. begin
  2917. hp:=FFirstblock;
  2918. while assigned(hp) do
  2919. begin
  2920. f.Write(hp^.data,hp^.used);
  2921. hp:=hp^.Next;
  2922. end;
  2923. end;
  2924. {****************************************************************************
  2925. TLinkStrMap
  2926. ****************************************************************************}
  2927. Constructor TLinkStrMap.create;
  2928. begin
  2929. inherited;
  2930. itemcnt:=0;
  2931. end;
  2932. procedure TLinkStrMap.Add(key:ansistring;value:AnsiString='';weight:longint=weightdefault);
  2933. begin
  2934. if lookup(key)<>-1 Then
  2935. exit;
  2936. if itemcnt<=length(fmap) Then
  2937. setlength(fmap,itemcnt+10);
  2938. fmap[itemcnt].key:=key;
  2939. fmap[itemcnt].value:=value;
  2940. fmap[itemcnt].weight:=weight;
  2941. inc(itemcnt);
  2942. end;
  2943. function TLinkStrMap.AddDep(keyvalue:String):boolean;
  2944. var i : Longint;
  2945. begin
  2946. AddDep:=false;
  2947. i:=pos('=',keyvalue);
  2948. if i=0 then
  2949. exit;
  2950. Add(Copy(KeyValue,1,i-1),Copy(KeyValue,i+1,length(KeyValue)-i));
  2951. AddDep:=True;
  2952. end;
  2953. function TLinkStrMap.AddWeight(keyvalue:String):boolean;
  2954. var i,j : Longint;
  2955. Code : Word;
  2956. s : AnsiString;
  2957. begin
  2958. AddWeight:=false;
  2959. i:=pos('=',keyvalue);
  2960. if i=0 then
  2961. exit;
  2962. s:=Copy(KeyValue,i+1,length(KeyValue)-i);
  2963. val(s,j,code);
  2964. if code=0 Then
  2965. begin
  2966. Add(Copy(KeyValue,1,i-1),'',j);
  2967. AddWeight:=True;
  2968. end;
  2969. end;
  2970. procedure TLinkStrMap.addseries(keys:AnsiString;weight:longint);
  2971. var i,j,k : longint;
  2972. begin
  2973. k:=length(keys);
  2974. i:=1;
  2975. while i<=k do
  2976. begin
  2977. j:=i;
  2978. while (i<=k) and (keys[i]<>',') do
  2979. inc(i);
  2980. add(copy(keys,j,i-j),'',weight);
  2981. inc(i);
  2982. end;
  2983. end;
  2984. procedure TLinkStrMap.SetValue(Key:Ansistring;weight:Integer);
  2985. var j : longint;
  2986. begin
  2987. j:=lookup(key);
  2988. if j<>-1 then
  2989. fmap[j].weight:=weight;
  2990. end;
  2991. function TLinkStrMap.find(key:Ansistring):Ansistring;
  2992. var j : longint;
  2993. begin
  2994. find:='';
  2995. j:=lookup(key);
  2996. if j<>-1 then
  2997. find:=fmap[j].value;
  2998. end;
  2999. function TLinkStrMap.lookup(key:Ansistring):longint;
  3000. var i : longint;
  3001. begin
  3002. lookup:=-1;
  3003. i:=0;
  3004. {$B-}
  3005. while (i<itemcnt) and (fmap[i].key<>key) do
  3006. inc(i);
  3007. {$B+}
  3008. if i<>itemcnt then
  3009. lookup:=i;
  3010. end;
  3011. procedure TLinkStrMap.SortOnWeight;
  3012. var i, j : longint;
  3013. m : TLinkRec;
  3014. begin
  3015. if itemcnt <2 then exit;
  3016. for i:=0 to itemcnt-1 do
  3017. for j:=i+1 to itemcnt-1 do
  3018. begin
  3019. if fmap[i].weight>fmap[j].weight Then
  3020. begin
  3021. m:=fmap[i];
  3022. fmap[i]:=fmap[j];
  3023. fmap[j]:=m;
  3024. end;
  3025. end;
  3026. end;
  3027. function TLinkStrMap.getlinkrec(i:longint):TLinkRec;
  3028. begin
  3029. result:=fmap[i];
  3030. end;
  3031. procedure TLinkStrMap.Expand(Src:TStringList;Dest:TLinkStrMap);
  3032. // expands every thing in Src to Dest for linkorder purposes.
  3033. var l,r : longint;
  3034. LibN : String;
  3035. begin
  3036. while not src.empty do
  3037. begin
  3038. LibN:=src.getfirst;
  3039. r:=lookup (LibN);
  3040. if r=-1 then
  3041. dest.add(LibN)
  3042. else
  3043. dest.addseries(fmap[r].value);
  3044. end;
  3045. end;
  3046. procedure TLinkStrMap.UpdateWeights(Weightmap:TLinkStrMap);
  3047. var l,r : longint;
  3048. begin
  3049. for l := 0 to itemcnt-1 do
  3050. begin
  3051. r:=weightmap.lookup (fmap[l].key);
  3052. if r<>-1 then
  3053. fmap[l].weight:=weightmap[r].weight;
  3054. end;
  3055. end;
  3056. end.