cclasses.pas 88 KB

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