cclasses.pas 88 KB

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