cclasses.pas 84 KB

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