cclasses.pas 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546
  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. cutils,cstreams;
  22. {********************************************
  23. TMemDebug
  24. ********************************************}
  25. type
  26. tmemdebug = class
  27. private
  28. totalmem,
  29. startmem : integer;
  30. infostr : string[40];
  31. public
  32. constructor Create(const s:string);
  33. destructor Destroy;override;
  34. procedure show;
  35. procedure start;
  36. procedure stop;
  37. end;
  38. {*******************************************************
  39. TList (Copied from FCL, exception handling stripped)
  40. ********************************************************}
  41. const
  42. MaxListSize = Maxint div 16;
  43. SListIndexError = 'List index exceeds bounds (%d)';
  44. SListCapacityError = 'The maximum list capacity is reached (%d)';
  45. SListCountError = 'List count too large (%d)';
  46. type
  47. { TList class }
  48. PPointerList = ^TPointerList;
  49. TPointerList = array[0..MaxListSize - 1] of Pointer;
  50. TListSortCompare = function (Item1, Item2: Pointer): Integer;
  51. TList = class(TObject)
  52. private
  53. FList: PPointerList;
  54. FCount: Integer;
  55. FCapacity: Integer;
  56. protected
  57. function Get(Index: Integer): Pointer;
  58. procedure Grow; virtual;
  59. procedure Put(Index: Integer; Item: Pointer);
  60. procedure SetCapacity(NewCapacity: Integer);
  61. procedure SetCount(NewCount: Integer);
  62. public
  63. destructor Destroy; override;
  64. function Add(Item: Pointer): Integer;
  65. procedure Clear; dynamic;
  66. procedure Delete(Index: Integer);
  67. class procedure Error(const Msg: string; Data: Integer); virtual;
  68. procedure Exchange(Index1, Index2: Integer);
  69. function Expand: TList;
  70. function Extract(item: Pointer): Pointer;
  71. function First: Pointer;
  72. procedure Assign(Obj:TList);
  73. function IndexOf(Item: Pointer): Integer;
  74. procedure Insert(Index: Integer; Item: Pointer);
  75. function Last: Pointer;
  76. procedure Move(CurIndex, NewIndex: Integer);
  77. function Remove(Item: Pointer): Integer;
  78. procedure Pack;
  79. procedure Sort(Compare: TListSortCompare);
  80. property Capacity: Integer read FCapacity write SetCapacity;
  81. property Count: Integer read FCount write SetCount;
  82. property Items[Index: Integer]: Pointer read Get write Put; default;
  83. property List: PPointerList read FList;
  84. end;
  85. {********************************************
  86. TLinkedList
  87. ********************************************}
  88. type
  89. TLinkedListItem = class
  90. public
  91. Previous,
  92. Next : TLinkedListItem;
  93. Constructor Create;
  94. Destructor Destroy;override;
  95. Function GetCopy:TLinkedListItem;virtual;
  96. end;
  97. TLinkedListItemClass = class of TLinkedListItem;
  98. TLinkedList = class
  99. private
  100. FCount : integer;
  101. FFirst,
  102. FLast : TLinkedListItem;
  103. FNoClear : boolean;
  104. public
  105. constructor Create;
  106. destructor Destroy;override;
  107. { true when the List is empty }
  108. function Empty:boolean;
  109. { deletes all Items }
  110. procedure Clear;
  111. { inserts an Item }
  112. procedure Insert(Item:TLinkedListItem);
  113. { inserts an Item before Loc }
  114. procedure InsertBefore(Item,Loc : TLinkedListItem);
  115. { inserts an Item after Loc }
  116. procedure InsertAfter(Item,Loc : TLinkedListItem);virtual;
  117. { concats an Item }
  118. procedure Concat(Item:TLinkedListItem);
  119. { deletes an Item }
  120. procedure Remove(Item:TLinkedListItem);
  121. { Gets First Item }
  122. function GetFirst:TLinkedListItem;
  123. { Gets last Item }
  124. function GetLast:TLinkedListItem;
  125. { inserts another List at the begin and make this List empty }
  126. procedure insertList(p : TLinkedList);
  127. { inserts another List before the provided item and make this List empty }
  128. procedure insertListBefore(Item:TLinkedListItem;p : TLinkedList);
  129. { inserts another List after the provided item and make this List empty }
  130. procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  131. { concats another List at the end and make this List empty }
  132. procedure concatList(p : TLinkedList);
  133. { concats another List at the start and makes a copy
  134. the list is ordered in reverse.
  135. }
  136. procedure insertListcopy(p : TLinkedList);
  137. { concats another List at the end and makes a copy }
  138. procedure concatListcopy(p : TLinkedList);
  139. property First:TLinkedListItem read FFirst;
  140. property Last:TLinkedListItem read FLast;
  141. property Count:Integer read FCount;
  142. property NoClear:boolean write FNoClear;
  143. end;
  144. {********************************************
  145. TStringList
  146. ********************************************}
  147. { string containerItem }
  148. TStringListItem = class(TLinkedListItem)
  149. FPStr : PString;
  150. public
  151. constructor Create(const s:string);
  152. destructor Destroy;override;
  153. function GetCopy:TLinkedListItem;override;
  154. function Str:string;
  155. end;
  156. { string container }
  157. TStringList = class(TLinkedList)
  158. private
  159. FDoubles : boolean; { if this is set to true, doubles are allowed }
  160. public
  161. constructor Create;
  162. constructor Create_No_Double;
  163. { inserts an Item }
  164. procedure Insert(const s:string);
  165. { concats an Item }
  166. procedure Concat(const s:string);
  167. { deletes an Item }
  168. procedure Remove(const s:string);
  169. { Gets First Item }
  170. function GetFirst:string;
  171. { Gets last Item }
  172. function GetLast:string;
  173. { true if string is in the container, compare case sensitive }
  174. function FindCase(const s:string):TStringListItem;
  175. { true if string is in the container }
  176. function Find(const s:string):TStringListItem;
  177. { inserts an item }
  178. procedure InsertItem(item:TStringListItem);
  179. { concats an item }
  180. procedure ConcatItem(item:TStringListItem);
  181. property Doubles:boolean read FDoubles write FDoubles;
  182. end;
  183. {********************************************
  184. Dictionary
  185. ********************************************}
  186. const
  187. { the real size will be [0..hasharray-1] ! }
  188. hasharraysize = 512;
  189. type
  190. { namedindexobect for use with dictionary and indexarray }
  191. TNamedIndexItem=class
  192. private
  193. { indexarray }
  194. FIndexNr : integer;
  195. FIndexNext : TNamedIndexItem;
  196. { dictionary }
  197. FLeft,
  198. FRight : TNamedIndexItem;
  199. FSpeedValue : cardinal;
  200. { singleList }
  201. FListNext : TNamedIndexItem;
  202. FName : Pstring;
  203. protected
  204. function GetName:string;virtual;
  205. procedure SetName(const n:string);virtual;
  206. public
  207. constructor Create;
  208. constructor CreateName(const n:string);
  209. destructor Destroy;override;
  210. property IndexNr:integer read FIndexNr write FIndexNr;
  211. property IndexNext:TNamedIndexItem read FIndexNext write FIndexNext;
  212. property Name:string read GetName write SetName;
  213. property SpeedValue:cardinal read FSpeedValue;
  214. property ListNext:TNamedIndexItem read FListNext;
  215. property Left:TNamedIndexItem read FLeft write FLeft;
  216. property Right:TNamedIndexItem read FRight write FRight;
  217. end;
  218. Pdictionaryhasharray=^Tdictionaryhasharray;
  219. Tdictionaryhasharray=array[0..hasharraysize-1] of TNamedIndexItem;
  220. TnamedIndexCallback = procedure(p:TNamedIndexItem;arg:pointer) of object;
  221. TnamedIndexStaticCallback = procedure(p:TNamedIndexItem;arg:pointer);
  222. Tdictionary=class
  223. private
  224. FRoot : TNamedIndexItem;
  225. FCount : longint;
  226. FHashArray : Pdictionaryhasharray;
  227. procedure cleartree(var obj:TNamedIndexItem);
  228. function insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  229. procedure inserttree(currtree,currroot:TNamedIndexItem);
  230. public
  231. noclear : boolean;
  232. delete_doubles : boolean;
  233. constructor Create;
  234. destructor Destroy;override;
  235. procedure usehash;
  236. procedure clear;
  237. function delete(const s:string):TNamedIndexItem;
  238. function empty:boolean;
  239. procedure foreach(proc2call:TNamedIndexcallback;arg:pointer);
  240. procedure foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  241. function insert(obj:TNamedIndexItem):TNamedIndexItem;
  242. function replace(oldobj,newobj:TNamedIndexItem):boolean;
  243. function rename(const olds,News : string):TNamedIndexItem;
  244. function search(const s:string):TNamedIndexItem;
  245. function speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  246. property Items[const s:string]:TNamedIndexItem read Search;default;
  247. property Count:longint read FCount;
  248. end;
  249. tsingleList=class
  250. First,
  251. last : TNamedIndexItem;
  252. constructor Create;
  253. procedure reset;
  254. procedure clear;
  255. procedure insert(p:TNamedIndexItem);
  256. end;
  257. tindexobjectarray=array[1..16000] of TNamedIndexItem;
  258. pnamedindexobjectarray=^tindexobjectarray;
  259. tindexarray=class
  260. noclear : boolean;
  261. First : TNamedIndexItem;
  262. count : integer;
  263. constructor Create(Agrowsize:integer);
  264. destructor destroy;override;
  265. procedure clear;
  266. procedure foreach(proc2call : Tnamedindexcallback;arg:pointer);
  267. procedure foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  268. procedure deleteindex(p:TNamedIndexItem);
  269. procedure delete(var p:TNamedIndexItem);
  270. procedure insert(p:TNamedIndexItem);
  271. procedure replace(oldp,newp:TNamedIndexItem);
  272. function search(nr:integer):TNamedIndexItem;
  273. private
  274. growsize,
  275. size : integer;
  276. data : pnamedindexobjectarray;
  277. procedure grow(gsize:integer);
  278. end;
  279. {********************************************
  280. DynamicArray
  281. ********************************************}
  282. const
  283. dynamicblockbasesize = 12;
  284. type
  285. pdynamicblock = ^tdynamicblock;
  286. tdynamicblock = record
  287. pos,
  288. used : integer;
  289. Next : pdynamicblock;
  290. { can't use sizeof(integer) because it crashes gdb }
  291. data : array[0..1024*1024] of byte;
  292. end;
  293. tdynamicarray = class
  294. private
  295. FPosn : integer;
  296. FPosnblock : pdynamicblock;
  297. FBlocksize : integer;
  298. FFirstblock,
  299. FLastblock : pdynamicblock;
  300. procedure grow;
  301. public
  302. constructor Create(Ablocksize:integer);
  303. destructor Destroy;override;
  304. procedure reset;
  305. function size:integer;
  306. procedure align(i:integer);
  307. procedure seek(i:integer);
  308. function read(var d;len:integer):integer;
  309. procedure write(const d;len:integer);
  310. procedure writestr(const s:string);
  311. procedure readstream(f:TCStream;maxlen:longint);
  312. procedure writestream(f:TCStream);
  313. property BlockSize : integer read FBlocksize;
  314. property FirstBlock : PDynamicBlock read FFirstBlock;
  315. property Pos : integer read FPosn;
  316. end;
  317. Const WeightDefault = 1000;
  318. Type
  319. TLinkRec = record
  320. Key : AnsiString;
  321. Value : AnsiString; // key expands to valuelist "value"
  322. Weight: longint;
  323. end;
  324. TLinkStrMap = class
  325. private
  326. itemcnt : longint;
  327. fmap : Array Of TLinkRec;
  328. function Lookup(key:Ansistring):longint;
  329. function getlinkrec(i:longint):TLinkRec;
  330. public
  331. procedure Add(key:ansistring;value:AnsiString='';weight:longint=weightdefault);
  332. procedure addseries(keys:AnsiString;weight:longint=weightdefault);
  333. function AddDep(keyvalue:String):boolean;
  334. function AddWeight(keyvalue:String):boolean;
  335. procedure SetValue(key:AnsiString;Weight:Integer);
  336. procedure SortonWeight;
  337. function Find(key:AnsiString):AnsiString;
  338. procedure Expand(src:TStringList;dest: TLinkStrMap);
  339. procedure UpdateWeights(Weightmap:TLinkStrMap);
  340. constructor Create;
  341. property count : longint read itemcnt;
  342. property items[I:longint]:TLinkRec read getlinkrec; default;
  343. end;
  344. implementation
  345. {*****************************************************************************
  346. Memory debug
  347. *****************************************************************************}
  348. constructor tmemdebug.create(const s:string);
  349. begin
  350. infostr:=s;
  351. totalmem:=0;
  352. Start;
  353. end;
  354. procedure tmemdebug.start;
  355. var
  356. status : TFPCHeapStatus;
  357. begin
  358. status:=GetFPCHeapStatus;
  359. startmem:=status.CurrHeapUsed;
  360. end;
  361. procedure tmemdebug.stop;
  362. var
  363. status : TFPCHeapStatus;
  364. begin
  365. if startmem<>0 then
  366. begin
  367. status:=GetFPCHeapStatus;
  368. inc(TotalMem,startmem-status.CurrHeapUsed);
  369. startmem:=0;
  370. end;
  371. end;
  372. destructor tmemdebug.destroy;
  373. begin
  374. Stop;
  375. show;
  376. end;
  377. procedure tmemdebug.show;
  378. begin
  379. write('memory [',infostr,'] ');
  380. if TotalMem>0 then
  381. writeln(DStr(TotalMem shr 10),' Kb released')
  382. else
  383. writeln(DStr((-TotalMem) shr 10),' Kb allocated');
  384. end;
  385. {*****************************************************************************
  386. TList
  387. *****************************************************************************}
  388. Const
  389. // Ratio of Pointer and Word Size.
  390. WordRatio = SizeOf(Pointer) Div SizeOf(Word);
  391. function TList.Get(Index: Integer): Pointer;
  392. begin
  393. If (Index<0) or (Index>=FCount) then
  394. Error(SListIndexError,Index);
  395. Result:=FList^[Index];
  396. end;
  397. procedure TList.Grow;
  398. begin
  399. // Only for compatibility with Delphi. Not needed.
  400. end;
  401. procedure TList.Put(Index: Integer; Item: Pointer);
  402. begin
  403. if (Index<0) or (Index>=FCount) then
  404. Error(SListIndexError,Index);
  405. Flist^[Index]:=Item;
  406. end;
  407. function TList.Extract(item: Pointer): Pointer;
  408. var
  409. i : Integer;
  410. begin
  411. result:=nil;
  412. i:=IndexOf(item);
  413. if i>=0 then
  414. begin
  415. Result:=item;
  416. FList^[i]:=nil;
  417. Delete(i);
  418. end;
  419. end;
  420. procedure TList.SetCapacity(NewCapacity: Integer);
  421. begin
  422. If (NewCapacity<0) or (NewCapacity>MaxListSize) then
  423. Error (SListCapacityError,NewCapacity);
  424. if NewCapacity=FCapacity then
  425. exit;
  426. ReallocMem(FList,SizeOf(Pointer)*NewCapacity);
  427. if NewCapacity > FCapacity then
  428. FillChar (FList^ [FCapacity],
  429. (NewCapacity - FCapacity) * SizeOf (pointer), 0);
  430. FCapacity:=NewCapacity;
  431. end;
  432. procedure TList.SetCount(NewCount: Integer);
  433. begin
  434. If (NewCount<0) or (NewCount>MaxListSize)then
  435. Error(SListCountError,NewCount);
  436. If NewCount<FCount then
  437. FCount:=NewCount
  438. else If NewCount>FCount then
  439. begin
  440. If NewCount>FCapacity then
  441. SetCapacity (NewCount);
  442. If FCount<NewCount then
  443. FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
  444. FCount:=Newcount;
  445. end;
  446. end;
  447. destructor TList.Destroy;
  448. begin
  449. Self.Clear;
  450. inherited Destroy;
  451. end;
  452. Function TList.Add(Item: Pointer): Integer;
  453. begin
  454. Self.Insert (Count,Item);
  455. Result:=Count-1;
  456. end;
  457. Procedure TList.Clear;
  458. begin
  459. If Assigned(FList) then
  460. begin
  461. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  462. FList:=Nil;
  463. FCapacity:=0;
  464. FCount:=0;
  465. end;
  466. end;
  467. Procedure TList.Delete(Index: Integer);
  468. begin
  469. If (Index<0) or (Index>=FCount) then
  470. Error (SListIndexError,Index);
  471. FCount:=FCount-1;
  472. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  473. // Shrink the list if appropiate
  474. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  475. begin
  476. FCapacity := FCapacity shr 1;
  477. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  478. end;
  479. end;
  480. class procedure TList.Error(const Msg: string; Data: Integer);
  481. {$ifdef EXTDEBUG}
  482. var
  483. s : string;
  484. {$endif EXTDEBUG}
  485. begin
  486. {$ifdef EXTDEBUG}
  487. s:=Msg;
  488. Replace(s,'%d',ToStr(Data));
  489. writeln(s);
  490. {$endif EXTDEBUG}
  491. internalerrorproc(200411151);
  492. end;
  493. procedure TList.Exchange(Index1, Index2: Integer);
  494. var Temp : Pointer;
  495. begin
  496. If ((Index1>=FCount) or (Index1<0)) then
  497. Error(SListIndexError,Index1);
  498. If ((Index2>=FCount) or (Index2<0)) then
  499. Error(SListIndexError,Index2);
  500. Temp:=FList^[Index1];
  501. FList^[Index1]:=FList^[Index2];
  502. FList^[Index2]:=Temp;
  503. end;
  504. function TList.Expand: TList;
  505. Var IncSize : Longint;
  506. begin
  507. if FCount<FCapacity then exit;
  508. IncSize:=4;
  509. if FCapacity>3 then IncSize:=IncSize+4;
  510. if FCapacity>8 then IncSize:=IncSize+8;
  511. if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
  512. SetCapacity(FCapacity+IncSize);
  513. Result:=Self;
  514. end;
  515. function TList.First: Pointer;
  516. begin
  517. If FCount=0 then
  518. Result:=Nil
  519. else
  520. Result:=Items[0];
  521. end;
  522. function TList.IndexOf(Item: Pointer): Integer;
  523. begin
  524. Result:=0;
  525. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  526. If Result=FCount then Result:=-1;
  527. end;
  528. procedure TList.Insert(Index: Integer; Item: Pointer);
  529. begin
  530. If (Index<0) or (Index>FCount )then
  531. Error(SlistIndexError,Index);
  532. IF FCount=FCapacity Then Self.Expand;
  533. If Index<FCount then
  534. System.Move(Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  535. FList^[Index]:=Item;
  536. FCount:=FCount+1;
  537. end;
  538. function TList.Last: Pointer;
  539. begin
  540. // Wouldn't it be better to return nil if the count is zero ?
  541. If FCount=0 then
  542. Result:=Nil
  543. else
  544. Result:=Items[FCount-1];
  545. end;
  546. procedure TList.Move(CurIndex, NewIndex: Integer);
  547. Var Temp : Pointer;
  548. begin
  549. If ((CurIndex<0) or (CurIndex>Count-1)) then
  550. Error(SListIndexError,CurIndex);
  551. If (NewINdex<0) then
  552. Error(SlistIndexError,NewIndex);
  553. Temp:=FList^[CurIndex];
  554. FList^[CurIndex]:=Nil;
  555. Self.Delete(CurIndex);
  556. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  557. // Newindex changes when deleting ??
  558. Self.Insert (NewIndex,Nil);
  559. FList^[NewIndex]:=Temp;
  560. end;
  561. function TList.Remove(Item: Pointer): Integer;
  562. begin
  563. Result:=IndexOf(Item);
  564. If Result<>-1 then
  565. Self.Delete (Result);
  566. end;
  567. Procedure TList.Pack;
  568. Var {Last,I,J,}Runner : Longint;
  569. begin
  570. // Not the fastest; but surely correct
  571. For Runner:=Fcount-1 downto 0 do
  572. if Items[Runner]=Nil then Self.Delete(Runner);
  573. { The following may be faster in case of large and defragmented lists
  574. If count=0 then exit;
  575. Runner:=0;I:=0;
  576. TheLast:=Count;
  577. while runner<count do
  578. begin
  579. // Find first Nil
  580. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  581. if Runner<Count do
  582. begin
  583. // Start searching for non-nil from last known nil+1
  584. if i<Runner then I:=Runner+1;
  585. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  586. // Start looking for last non-nil of block.
  587. J:=I+1;
  588. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  589. // Move block and zero out
  590. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  591. FillWord (Flist^[I],(J-I)*WordRatio,0);
  592. // Update Runner and Last to point behind last block
  593. TheLast:=Runner+(J-I);
  594. If J=Count then
  595. begin
  596. // Shortcut, when J=Count we checked all pointers
  597. Runner:=Count
  598. else
  599. begin
  600. Runner:=TheLast;
  601. I:=j;
  602. end;
  603. end;
  604. Count:=TheLast;
  605. }
  606. end;
  607. // Needed by Sort method.
  608. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  609. Compare : TListSortCompare);
  610. Var I,J : Longint;
  611. P,Q : Pointer;
  612. begin
  613. Repeat
  614. I:=L;
  615. J:=R;
  616. P:=FList^[ (L+R) div 2 ];
  617. repeat
  618. While Compare(P,FList^[i])>0 Do I:=I+1;
  619. While Compare(P,FList^[J])<0 Do J:=J-1;
  620. If I<=J then
  621. begin
  622. Q:=Flist^[I];
  623. Flist^[I]:=FList^[J];
  624. FList^[J]:=Q;
  625. I:=I+1;
  626. J:=j-1;
  627. end;
  628. Until I>J;
  629. If L<J then QuickSort (FList,L,J,Compare);
  630. L:=I;
  631. Until I>=R;
  632. end;
  633. procedure TList.Sort(Compare: TListSortCompare);
  634. begin
  635. If Not Assigned(FList) or (FCount<2) then exit;
  636. QuickSort (Flist, 0, FCount-1,Compare);
  637. end;
  638. procedure TList.Assign(Obj:TList);
  639. // Principle copied from TCollection
  640. var i : Integer;
  641. begin
  642. Clear;
  643. For I:=0 To Obj.Count-1 Do
  644. Add(Obj[i]);
  645. end;
  646. {****************************************************************************
  647. TLinkedListItem
  648. ****************************************************************************}
  649. constructor TLinkedListItem.Create;
  650. begin
  651. Previous:=nil;
  652. Next:=nil;
  653. end;
  654. destructor TLinkedListItem.Destroy;
  655. begin
  656. end;
  657. function TLinkedListItem.GetCopy:TLinkedListItem;
  658. var
  659. p : TLinkedListItem;
  660. l : integer;
  661. begin
  662. p:=TLinkedListItemClass(ClassType).Create;
  663. l:=InstanceSize;
  664. Move(pointer(self)^,pointer(p)^,l);
  665. Result:=p;
  666. end;
  667. {****************************************************************************
  668. TLinkedList
  669. ****************************************************************************}
  670. constructor TLinkedList.Create;
  671. begin
  672. FFirst:=nil;
  673. Flast:=nil;
  674. FCount:=0;
  675. FNoClear:=False;
  676. end;
  677. destructor TLinkedList.destroy;
  678. begin
  679. if not FNoClear then
  680. Clear;
  681. end;
  682. function TLinkedList.empty:boolean;
  683. begin
  684. Empty:=(FFirst=nil);
  685. end;
  686. procedure TLinkedList.Insert(Item:TLinkedListItem);
  687. begin
  688. if FFirst=nil then
  689. begin
  690. FLast:=Item;
  691. Item.Previous:=nil;
  692. Item.Next:=nil;
  693. end
  694. else
  695. begin
  696. FFirst.Previous:=Item;
  697. Item.Previous:=nil;
  698. Item.Next:=FFirst;
  699. end;
  700. FFirst:=Item;
  701. inc(FCount);
  702. end;
  703. procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
  704. begin
  705. Item.Previous:=Loc.Previous;
  706. Item.Next:=Loc;
  707. Loc.Previous:=Item;
  708. if assigned(Item.Previous) then
  709. Item.Previous.Next:=Item
  710. else
  711. { if we've no next item, we've to adjust FFist }
  712. FFirst:=Item;
  713. inc(FCount);
  714. end;
  715. procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
  716. begin
  717. Item.Next:=Loc.Next;
  718. Loc.Next:=Item;
  719. Item.Previous:=Loc;
  720. if assigned(Item.Next) then
  721. Item.Next.Previous:=Item
  722. else
  723. { if we've no next item, we've to adjust FLast }
  724. FLast:=Item;
  725. inc(FCount);
  726. end;
  727. procedure TLinkedList.Concat(Item:TLinkedListItem);
  728. begin
  729. if FFirst=nil then
  730. begin
  731. FFirst:=Item;
  732. Item.Previous:=nil;
  733. Item.Next:=nil;
  734. end
  735. else
  736. begin
  737. Flast.Next:=Item;
  738. Item.Previous:=Flast;
  739. Item.Next:=nil;
  740. end;
  741. Flast:=Item;
  742. inc(FCount);
  743. end;
  744. procedure TLinkedList.remove(Item:TLinkedListItem);
  745. begin
  746. if Item=nil then
  747. exit;
  748. if (FFirst=Item) and (Flast=Item) then
  749. begin
  750. FFirst:=nil;
  751. Flast:=nil;
  752. end
  753. else if FFirst=Item then
  754. begin
  755. FFirst:=Item.Next;
  756. if assigned(FFirst) then
  757. FFirst.Previous:=nil;
  758. end
  759. else if Flast=Item then
  760. begin
  761. Flast:=Flast.Previous;
  762. if assigned(Flast) then
  763. Flast.Next:=nil;
  764. end
  765. else
  766. begin
  767. Item.Previous.Next:=Item.Next;
  768. Item.Next.Previous:=Item.Previous;
  769. end;
  770. Item.Next:=nil;
  771. Item.Previous:=nil;
  772. dec(FCount);
  773. end;
  774. procedure TLinkedList.clear;
  775. var
  776. NewNode : TLinkedListItem;
  777. begin
  778. NewNode:=FFirst;
  779. while assigned(NewNode) do
  780. begin
  781. FFirst:=NewNode.Next;
  782. NewNode.Free;
  783. NewNode:=FFirst;
  784. end;
  785. FLast:=nil;
  786. FFirst:=nil;
  787. FCount:=0;
  788. end;
  789. function TLinkedList.GetFirst:TLinkedListItem;
  790. begin
  791. if FFirst=nil then
  792. GetFirst:=nil
  793. else
  794. begin
  795. GetFirst:=FFirst;
  796. if FFirst=FLast then
  797. FLast:=nil;
  798. FFirst:=FFirst.Next;
  799. dec(FCount);
  800. end;
  801. end;
  802. function TLinkedList.GetLast:TLinkedListItem;
  803. begin
  804. if FLast=nil then
  805. Getlast:=nil
  806. else
  807. begin
  808. Getlast:=FLast;
  809. if FLast=FFirst then
  810. FFirst:=nil;
  811. FLast:=FLast.Previous;
  812. dec(FCount);
  813. end;
  814. end;
  815. procedure TLinkedList.insertList(p : TLinkedList);
  816. begin
  817. { empty List ? }
  818. if (p.FFirst=nil) then
  819. exit;
  820. p.Flast.Next:=FFirst;
  821. { we have a double Linked List }
  822. if assigned(FFirst) then
  823. FFirst.Previous:=p.Flast;
  824. FFirst:=p.FFirst;
  825. if (FLast=nil) then
  826. Flast:=p.Flast;
  827. inc(FCount,p.FCount);
  828. { p becomes empty }
  829. p.FFirst:=nil;
  830. p.Flast:=nil;
  831. p.FCount:=0;
  832. end;
  833. procedure TLinkedList.insertListBefore(Item:TLinkedListItem;p : TLinkedList);
  834. begin
  835. { empty List ? }
  836. if (p.FFirst=nil) then
  837. exit;
  838. if (Item=nil) then
  839. begin
  840. { Insert at begin }
  841. InsertList(p);
  842. exit;
  843. end
  844. else
  845. begin
  846. p.FLast.Next:=Item;
  847. p.FFirst.Previous:=Item.Previous;
  848. if assigned(Item.Previous) then
  849. Item.Previous.Next:=p.FFirst
  850. else
  851. FFirst:=p.FFirst;
  852. Item.Previous:=p.FLast;
  853. inc(FCount,p.FCount);
  854. end;
  855. { p becomes empty }
  856. p.FFirst:=nil;
  857. p.Flast:=nil;
  858. p.FCount:=0;
  859. end;
  860. procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  861. begin
  862. { empty List ? }
  863. if (p.FFirst=nil) then
  864. exit;
  865. if (Item=nil) then
  866. begin
  867. { Insert at begin }
  868. InsertList(p);
  869. exit;
  870. end
  871. else
  872. begin
  873. p.FFirst.Previous:=Item;
  874. p.FLast.Next:=Item.Next;
  875. if assigned(Item.Next) then
  876. Item.Next.Previous:=p.FLast
  877. else
  878. FLast:=p.FLast;
  879. Item.Next:=p.FFirst;
  880. inc(FCount,p.FCount);
  881. end;
  882. { p becomes empty }
  883. p.FFirst:=nil;
  884. p.Flast:=nil;
  885. p.FCount:=0;
  886. end;
  887. procedure TLinkedList.concatList(p : TLinkedList);
  888. begin
  889. if (p.FFirst=nil) then
  890. exit;
  891. if FFirst=nil then
  892. FFirst:=p.FFirst
  893. else
  894. begin
  895. FLast.Next:=p.FFirst;
  896. p.FFirst.Previous:=Flast;
  897. end;
  898. Flast:=p.Flast;
  899. inc(FCount,p.FCount);
  900. { make p empty }
  901. p.Flast:=nil;
  902. p.FFirst:=nil;
  903. p.FCount:=0;
  904. end;
  905. procedure TLinkedList.insertListcopy(p : TLinkedList);
  906. var
  907. NewNode,NewNode2 : TLinkedListItem;
  908. begin
  909. NewNode:=p.First;
  910. while assigned(NewNode) do
  911. begin
  912. NewNode2:=NewNode.Getcopy;
  913. if assigned(NewNode2) then
  914. Insert(NewNode2);
  915. NewNode:=NewNode.Next;
  916. end;
  917. end;
  918. procedure TLinkedList.concatListcopy(p : TLinkedList);
  919. var
  920. NewNode,NewNode2 : TLinkedListItem;
  921. begin
  922. NewNode:=p.First;
  923. while assigned(NewNode) do
  924. begin
  925. NewNode2:=NewNode.Getcopy;
  926. if assigned(NewNode2) then
  927. Concat(NewNode2);
  928. NewNode:=NewNode.Next;
  929. end;
  930. end;
  931. {****************************************************************************
  932. TStringListItem
  933. ****************************************************************************}
  934. constructor TStringListItem.Create(const s:string);
  935. begin
  936. inherited Create;
  937. FPStr:=stringdup(s);
  938. end;
  939. destructor TStringListItem.Destroy;
  940. begin
  941. stringdispose(FPStr);
  942. end;
  943. function TStringListItem.Str:string;
  944. begin
  945. Str:=FPStr^;
  946. end;
  947. function TStringListItem.GetCopy:TLinkedListItem;
  948. begin
  949. Result:=(inherited GetCopy);
  950. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  951. end;
  952. {****************************************************************************
  953. TSTRINGList
  954. ****************************************************************************}
  955. constructor tstringList.Create;
  956. begin
  957. inherited Create;
  958. FDoubles:=true;
  959. end;
  960. constructor tstringList.Create_no_double;
  961. begin
  962. inherited Create;
  963. FDoubles:=false;
  964. end;
  965. procedure tstringList.insert(const s : string);
  966. begin
  967. if (s='') or
  968. ((not FDoubles) and (find(s)<>nil)) then
  969. exit;
  970. inherited insert(tstringListItem.create(s));
  971. end;
  972. procedure tstringList.concat(const s : string);
  973. begin
  974. if (s='') or
  975. ((not FDoubles) and (find(s)<>nil)) then
  976. exit;
  977. inherited concat(tstringListItem.create(s));
  978. end;
  979. procedure tstringList.remove(const s : string);
  980. var
  981. p : tstringListItem;
  982. begin
  983. if s='' then
  984. exit;
  985. p:=find(s);
  986. if assigned(p) then
  987. begin
  988. inherited Remove(p);
  989. p.Free;
  990. end;
  991. end;
  992. function tstringList.GetFirst : string;
  993. var
  994. p : tstringListItem;
  995. begin
  996. p:=tstringListItem(inherited GetFirst);
  997. if p=nil then
  998. GetFirst:=''
  999. else
  1000. begin
  1001. GetFirst:=p.FPStr^;
  1002. p.free;
  1003. end;
  1004. end;
  1005. function tstringList.Getlast : string;
  1006. var
  1007. p : tstringListItem;
  1008. begin
  1009. p:=tstringListItem(inherited Getlast);
  1010. if p=nil then
  1011. Getlast:=''
  1012. else
  1013. begin
  1014. Getlast:=p.FPStr^;
  1015. p.free;
  1016. end;
  1017. end;
  1018. function tstringList.FindCase(const s:string):TstringListItem;
  1019. var
  1020. NewNode : tstringListItem;
  1021. begin
  1022. result:=nil;
  1023. if s='' then
  1024. exit;
  1025. NewNode:=tstringListItem(FFirst);
  1026. while assigned(NewNode) do
  1027. begin
  1028. if NewNode.FPStr^=s then
  1029. begin
  1030. result:=NewNode;
  1031. exit;
  1032. end;
  1033. NewNode:=tstringListItem(NewNode.Next);
  1034. end;
  1035. end;
  1036. function tstringList.Find(const s:string):TstringListItem;
  1037. var
  1038. NewNode : tstringListItem;
  1039. ups : string;
  1040. begin
  1041. result:=nil;
  1042. if s='' then
  1043. exit;
  1044. ups:=upper(s);
  1045. NewNode:=tstringListItem(FFirst);
  1046. while assigned(NewNode) do
  1047. begin
  1048. if upper(NewNode.FPStr^)=ups then
  1049. begin
  1050. result:=NewNode;
  1051. exit;
  1052. end;
  1053. NewNode:=tstringListItem(NewNode.Next);
  1054. end;
  1055. end;
  1056. procedure TStringList.InsertItem(item:TStringListItem);
  1057. begin
  1058. inherited Insert(item);
  1059. end;
  1060. procedure TStringList.ConcatItem(item:TStringListItem);
  1061. begin
  1062. inherited Concat(item);
  1063. end;
  1064. {****************************************************************************
  1065. TNamedIndexItem
  1066. ****************************************************************************}
  1067. constructor TNamedIndexItem.Create;
  1068. begin
  1069. { index }
  1070. Findexnr:=-1;
  1071. FindexNext:=nil;
  1072. { dictionary }
  1073. Fleft:=nil;
  1074. Fright:=nil;
  1075. FName:=nil;
  1076. Fspeedvalue:=cardinal($ffffffff);
  1077. { List }
  1078. FListNext:=nil;
  1079. end;
  1080. constructor TNamedIndexItem.Createname(const n:string);
  1081. begin
  1082. { index }
  1083. Findexnr:=-1;
  1084. FindexNext:=nil;
  1085. { dictionary }
  1086. Fleft:=nil;
  1087. Fright:=nil;
  1088. fspeedvalue:=getspeedvalue(n);
  1089. {$ifdef compress}
  1090. FName:=stringdup(minilzw_encode(n));
  1091. {$else}
  1092. FName:=stringdup(n);
  1093. {$endif}
  1094. { List }
  1095. FListNext:=nil;
  1096. end;
  1097. destructor TNamedIndexItem.destroy;
  1098. begin
  1099. stringdispose(FName);
  1100. end;
  1101. procedure TNamedIndexItem.setname(const n:string);
  1102. begin
  1103. if assigned(FName) then
  1104. stringdispose(FName);
  1105. fspeedvalue:=getspeedvalue(n);
  1106. {$ifdef compress}
  1107. FName:=stringdup(minilzw_encode(n));
  1108. {$else}
  1109. FName:=stringdup(n);
  1110. {$endif}
  1111. end;
  1112. function TNamedIndexItem.GetName:string;
  1113. begin
  1114. if assigned(FName) then
  1115. {$ifdef compress}
  1116. Getname:=minilzw_decode(FName^)
  1117. {$else}
  1118. Getname:=FName^
  1119. {$endif}
  1120. else
  1121. Getname:='';
  1122. end;
  1123. {****************************************************************************
  1124. TDICTIONARY
  1125. ****************************************************************************}
  1126. constructor Tdictionary.Create;
  1127. begin
  1128. FRoot:=nil;
  1129. FHashArray:=nil;
  1130. noclear:=false;
  1131. delete_doubles:=false;
  1132. end;
  1133. procedure Tdictionary.usehash;
  1134. begin
  1135. if not(assigned(FRoot)) and
  1136. not(assigned(FHashArray)) then
  1137. begin
  1138. New(FHashArray);
  1139. fillchar(FHashArray^,sizeof(FHashArray^),0);
  1140. end;
  1141. end;
  1142. function counttree(p: tnamedindexitem): longint;
  1143. begin
  1144. counttree:=0;
  1145. if not assigned(p) then
  1146. exit;
  1147. result := 1;
  1148. inc(result,counttree(p.fleft));
  1149. inc(result,counttree(p.fright));
  1150. end;
  1151. destructor Tdictionary.destroy;
  1152. begin
  1153. if not noclear then
  1154. clear;
  1155. if assigned(FHashArray) then
  1156. begin
  1157. dispose(FHashArray);
  1158. end;
  1159. end;
  1160. procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
  1161. begin
  1162. if assigned(obj.Fleft) then
  1163. cleartree(obj.FLeft);
  1164. if assigned(obj.FRight) then
  1165. cleartree(obj.FRight);
  1166. obj.free;
  1167. obj:=nil;
  1168. end;
  1169. procedure Tdictionary.clear;
  1170. var
  1171. w : integer;
  1172. begin
  1173. if assigned(FRoot) then
  1174. cleartree(FRoot);
  1175. if assigned(FHashArray) then
  1176. for w:= low(FHashArray^) to high(FHashArray^) do
  1177. if assigned(FHashArray^[w]) then
  1178. cleartree(FHashArray^[w]);
  1179. end;
  1180. function Tdictionary.delete(const s:string):TNamedIndexItem;
  1181. var
  1182. p,SpeedValue : cardinal;
  1183. n : TNamedIndexItem;
  1184. {$ifdef compress}
  1185. senc:string;
  1186. {$else}
  1187. senc:string absolute s;
  1188. {$endif}
  1189. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  1190. begin
  1191. while root.FRight<>nil do
  1192. root:=root.FRight;
  1193. root.FRight:=Atree;
  1194. end;
  1195. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  1196. type
  1197. leftright=(left,right);
  1198. var
  1199. lr : leftright;
  1200. oldroot : TNamedIndexItem;
  1201. begin
  1202. oldroot:=nil;
  1203. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  1204. begin
  1205. oldroot:=root;
  1206. if SpeedValue<root.SpeedValue then
  1207. begin
  1208. root:=root.FRight;
  1209. lr:=right;
  1210. end
  1211. else
  1212. begin
  1213. root:=root.FLeft;
  1214. lr:=left;
  1215. end;
  1216. end;
  1217. while (root<>nil) and (root.FName^<>senc) do
  1218. begin
  1219. oldroot:=root;
  1220. if senc<root.FName^ then
  1221. begin
  1222. root:=root.FRight;
  1223. lr:=right;
  1224. end
  1225. else
  1226. begin
  1227. root:=root.FLeft;
  1228. lr:=left;
  1229. end;
  1230. end;
  1231. if root<>nil then
  1232. begin
  1233. dec(FCount);
  1234. if root.FLeft<>nil then
  1235. begin
  1236. { Now the Node pointing to root must point to the left
  1237. subtree of root. The right subtree of root must be
  1238. connected to the right bottom of the left subtree.}
  1239. if lr=left then
  1240. oldroot.FLeft:=root.FLeft
  1241. else
  1242. oldroot.FRight:=root.FLeft;
  1243. if root.FRight<>nil then
  1244. insert_right_bottom(root.FLeft,root.FRight);
  1245. end
  1246. else
  1247. begin
  1248. { There is no left subtree. So we can just replace the Node to
  1249. delete with the right subtree.}
  1250. if lr=left then
  1251. oldroot.FLeft:=root.FRight
  1252. else
  1253. oldroot.FRight:=root.FRight;
  1254. end;
  1255. end;
  1256. delete_from_tree:=root;
  1257. end;
  1258. begin
  1259. {$ifdef compress}
  1260. senc:=minilzw_encode(s);
  1261. {$endif}
  1262. SpeedValue:=GetSpeedValue(s);
  1263. n:=FRoot;
  1264. if assigned(FHashArray) then
  1265. begin
  1266. { First, check if the Node to delete directly located under
  1267. the hasharray.}
  1268. p:=SpeedValue mod hasharraysize;
  1269. n:=FHashArray^[p];
  1270. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  1271. (n.FName^=senc) then
  1272. begin
  1273. { The Node to delete is directly located under the
  1274. hasharray. Make the hasharray point to the left
  1275. subtree of the Node and place the right subtree on
  1276. the right-bottom of the left subtree.}
  1277. if n.FLeft<>nil then
  1278. begin
  1279. FHashArray^[p]:=n.FLeft;
  1280. if n.FRight<>nil then
  1281. insert_right_bottom(n.FLeft,n.FRight);
  1282. end
  1283. else
  1284. FHashArray^[p]:=n.FRight;
  1285. delete:=n;
  1286. dec(FCount);
  1287. exit;
  1288. end;
  1289. end
  1290. else
  1291. begin
  1292. { First check if the Node to delete is the root.}
  1293. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  1294. (n.FName^=senc) then
  1295. begin
  1296. if n.FLeft<>nil then
  1297. begin
  1298. FRoot:=n.FLeft;
  1299. if n.FRight<>nil then
  1300. insert_right_bottom(n.FLeft,n.FRight);
  1301. end
  1302. else
  1303. FRoot:=n.FRight;
  1304. delete:=n;
  1305. dec(FCount);
  1306. exit;
  1307. end;
  1308. end;
  1309. delete:=delete_from_tree(n);
  1310. end;
  1311. function Tdictionary.empty:boolean;
  1312. var
  1313. w : integer;
  1314. begin
  1315. if assigned(FHashArray) then
  1316. begin
  1317. empty:=false;
  1318. for w:=low(FHashArray^) to high(FHashArray^) do
  1319. if assigned(FHashArray^[w]) then
  1320. exit;
  1321. empty:=true;
  1322. end
  1323. else
  1324. empty:=(FRoot=nil);
  1325. end;
  1326. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
  1327. procedure a(p:TNamedIndexItem;arg:pointer);
  1328. begin
  1329. proc2call(p,arg);
  1330. if assigned(p.FLeft) then
  1331. a(p.FLeft,arg);
  1332. if assigned(p.FRight) then
  1333. a(p.FRight,arg);
  1334. end;
  1335. var
  1336. i : integer;
  1337. begin
  1338. if assigned(FHashArray) then
  1339. begin
  1340. for i:=low(FHashArray^) to high(FHashArray^) do
  1341. if assigned(FHashArray^[i]) then
  1342. a(FHashArray^[i],arg);
  1343. end
  1344. else
  1345. if assigned(FRoot) then
  1346. a(FRoot,arg);
  1347. end;
  1348. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  1349. procedure a(p:TNamedIndexItem;arg:pointer);
  1350. begin
  1351. proc2call(p,arg);
  1352. if assigned(p.FLeft) then
  1353. a(p.FLeft,arg);
  1354. if assigned(p.FRight) then
  1355. a(p.FRight,arg);
  1356. end;
  1357. var
  1358. i : integer;
  1359. begin
  1360. if assigned(FHashArray) then
  1361. begin
  1362. for i:=low(FHashArray^) to high(FHashArray^) do
  1363. if assigned(FHashArray^[i]) then
  1364. a(FHashArray^[i],arg);
  1365. end
  1366. else
  1367. if assigned(FRoot) then
  1368. a(FRoot,arg);
  1369. end;
  1370. function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
  1371. var
  1372. hp : TNamedIndexItem;
  1373. begin
  1374. hp:=nil;
  1375. Replace:=false;
  1376. { must be the same name and hash }
  1377. if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
  1378. (oldobj.FName^<>newobj.FName^) then
  1379. exit;
  1380. { copy tree info }
  1381. newobj.FLeft:=oldobj.FLeft;
  1382. newobj.FRight:=oldobj.FRight;
  1383. { update treeroot }
  1384. if assigned(FHashArray) then
  1385. begin
  1386. hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
  1387. if hp=oldobj then
  1388. begin
  1389. FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
  1390. hp:=nil;
  1391. end;
  1392. end
  1393. else
  1394. begin
  1395. hp:=FRoot;
  1396. if hp=oldobj then
  1397. begin
  1398. FRoot:=newobj;
  1399. hp:=nil;
  1400. end;
  1401. end;
  1402. { update parent entry }
  1403. while assigned(hp) do
  1404. begin
  1405. { is the node to replace the left or right, then
  1406. update this node and stop }
  1407. if hp.FLeft=oldobj then
  1408. begin
  1409. hp.FLeft:=newobj;
  1410. break;
  1411. end;
  1412. if hp.FRight=oldobj then
  1413. begin
  1414. hp.FRight:=newobj;
  1415. break;
  1416. end;
  1417. { First check SpeedValue, to allow a fast insert }
  1418. if hp.SpeedValue>oldobj.SpeedValue then
  1419. hp:=hp.FRight
  1420. else
  1421. if hp.SpeedValue<oldobj.SpeedValue then
  1422. hp:=hp.FLeft
  1423. else
  1424. begin
  1425. if (hp.FName^=oldobj.FName^) then
  1426. begin
  1427. { this can never happend, return error }
  1428. exit;
  1429. end
  1430. else
  1431. if oldobj.FName^>hp.FName^ then
  1432. hp:=hp.FLeft
  1433. else
  1434. hp:=hp.FRight;
  1435. end;
  1436. end;
  1437. Replace:=true;
  1438. end;
  1439. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  1440. begin
  1441. inc(FCount);
  1442. if assigned(FHashArray) then
  1443. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  1444. else
  1445. insert:=insertNode(obj,FRoot);
  1446. end;
  1447. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  1448. begin
  1449. if currNode=nil then
  1450. begin
  1451. currNode:=NewNode;
  1452. insertNode:=NewNode;
  1453. end
  1454. { First check SpeedValue, to allow a fast insert }
  1455. else
  1456. if currNode.SpeedValue>NewNode.SpeedValue then
  1457. insertNode:=insertNode(NewNode,currNode.FRight)
  1458. else
  1459. if currNode.SpeedValue<NewNode.SpeedValue then
  1460. insertNode:=insertNode(NewNode,currNode.FLeft)
  1461. else
  1462. begin
  1463. if currNode.FName^>NewNode.FName^ then
  1464. insertNode:=insertNode(NewNode,currNode.FRight)
  1465. else
  1466. if currNode.FName^<NewNode.FName^ then
  1467. insertNode:=insertNode(NewNode,currNode.FLeft)
  1468. else
  1469. begin
  1470. if (delete_doubles) and
  1471. assigned(currNode) then
  1472. begin
  1473. NewNode.FLeft:=currNode.FLeft;
  1474. NewNode.FRight:=currNode.FRight;
  1475. if delete_doubles then
  1476. begin
  1477. currnode.FLeft:=nil;
  1478. currnode.FRight:=nil;
  1479. currnode.free;
  1480. end;
  1481. currNode:=NewNode;
  1482. insertNode:=NewNode;
  1483. end
  1484. else
  1485. insertNode:=currNode;
  1486. end;
  1487. end;
  1488. end;
  1489. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  1490. begin
  1491. if assigned(currtree) then
  1492. begin
  1493. inserttree(currtree.FLeft,currroot);
  1494. inserttree(currtree.FRight,currroot);
  1495. currtree.FRight:=nil;
  1496. currtree.FLeft:=nil;
  1497. insertNode(currtree,currroot);
  1498. end;
  1499. end;
  1500. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  1501. var
  1502. spdval : cardinal;
  1503. lasthp,
  1504. hp,hp2,hp3 : TNamedIndexItem;
  1505. {$ifdef compress}
  1506. oldsenc,newsenc:string;
  1507. {$else}
  1508. oldsenc:string absolute olds;
  1509. newsenc:string absolute news;
  1510. {$endif}
  1511. begin
  1512. {$ifdef compress}
  1513. oldsenc:=minilzw_encode(olds);
  1514. newsenc:=minilzw_encode(news);
  1515. {$endif}
  1516. spdval:=GetSpeedValue(olds);
  1517. if assigned(FHashArray) then
  1518. hp:=FHashArray^[spdval mod hasharraysize]
  1519. else
  1520. hp:=FRoot;
  1521. lasthp:=nil;
  1522. while assigned(hp) do
  1523. begin
  1524. if spdval>hp.SpeedValue then
  1525. begin
  1526. lasthp:=hp;
  1527. hp:=hp.FLeft
  1528. end
  1529. else
  1530. if spdval<hp.SpeedValue then
  1531. begin
  1532. lasthp:=hp;
  1533. hp:=hp.FRight
  1534. end
  1535. else
  1536. begin
  1537. if (hp.FName^=oldsenc) then
  1538. begin
  1539. { Get in hp2 the replacer for the root or hasharr }
  1540. hp2:=hp.FLeft;
  1541. hp3:=hp.FRight;
  1542. if not assigned(hp2) then
  1543. begin
  1544. hp2:=hp.FRight;
  1545. hp3:=hp.FLeft;
  1546. end;
  1547. { remove entry from the tree }
  1548. if assigned(lasthp) then
  1549. begin
  1550. if lasthp.FLeft=hp then
  1551. lasthp.FLeft:=hp2
  1552. else
  1553. lasthp.FRight:=hp2;
  1554. end
  1555. else
  1556. begin
  1557. if assigned(FHashArray) then
  1558. FHashArray^[spdval mod hasharraysize]:=hp2
  1559. else
  1560. FRoot:=hp2;
  1561. end;
  1562. { reinsert the hp3 in the tree from hp2 }
  1563. inserttree(hp3,hp2);
  1564. { reset Node with New values }
  1565. hp.FLeft:=nil;
  1566. hp.FRight:=nil;
  1567. stringdispose(hp.FName);
  1568. hp.FName:=stringdup(newsenc);
  1569. hp.FSpeedValue:=GetSpeedValue(news);
  1570. { reinsert }
  1571. if assigned(FHashArray) then
  1572. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  1573. else
  1574. rename:=insertNode(hp,FRoot);
  1575. exit;
  1576. end
  1577. else
  1578. if oldsenc>hp.FName^ then
  1579. begin
  1580. lasthp:=hp;
  1581. hp:=hp.FLeft
  1582. end
  1583. else
  1584. begin
  1585. lasthp:=hp;
  1586. hp:=hp.FRight;
  1587. end;
  1588. end;
  1589. end;
  1590. result := nil;
  1591. end;
  1592. function Tdictionary.search(const s:string):TNamedIndexItem;
  1593. begin
  1594. search:=speedsearch(s,getspeedvalue(s));
  1595. end;
  1596. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  1597. var
  1598. NewNode:TNamedIndexItem;
  1599. {$ifdef compress}
  1600. decn:string;
  1601. {$endif}
  1602. begin
  1603. if assigned(FHashArray) then
  1604. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  1605. else
  1606. NewNode:=FRoot;
  1607. while assigned(NewNode) do
  1608. begin
  1609. if SpeedValue>NewNode.SpeedValue then
  1610. NewNode:=NewNode.FLeft
  1611. else
  1612. if SpeedValue<NewNode.SpeedValue then
  1613. NewNode:=NewNode.FRight
  1614. else
  1615. begin
  1616. {$ifdef compress}
  1617. decn:=minilzw_decode(newnode.fname^);
  1618. if (decn=s) then
  1619. begin
  1620. speedsearch:=NewNode;
  1621. exit;
  1622. end
  1623. else
  1624. if s>decn then
  1625. NewNode:=NewNode.FLeft
  1626. else
  1627. NewNode:=NewNode.FRight;
  1628. {$else}
  1629. if (NewNode.FName^=s) then
  1630. begin
  1631. speedsearch:=NewNode;
  1632. exit;
  1633. end
  1634. else
  1635. if s>NewNode.FName^ then
  1636. NewNode:=NewNode.FLeft
  1637. else
  1638. NewNode:=NewNode.FRight;
  1639. {$endif}
  1640. end;
  1641. end;
  1642. speedsearch:=nil;
  1643. end;
  1644. {****************************************************************************
  1645. tsingleList
  1646. ****************************************************************************}
  1647. constructor tsingleList.create;
  1648. begin
  1649. First:=nil;
  1650. last:=nil;
  1651. end;
  1652. procedure tsingleList.reset;
  1653. begin
  1654. First:=nil;
  1655. last:=nil;
  1656. end;
  1657. procedure tsingleList.clear;
  1658. var
  1659. hp,hp2 : TNamedIndexItem;
  1660. begin
  1661. hp:=First;
  1662. while assigned(hp) do
  1663. begin
  1664. hp2:=hp;
  1665. hp:=hp.FListNext;
  1666. hp2.free;
  1667. end;
  1668. First:=nil;
  1669. last:=nil;
  1670. end;
  1671. procedure tsingleList.insert(p:TNamedIndexItem);
  1672. begin
  1673. if not assigned(First) then
  1674. First:=p
  1675. else
  1676. last.FListNext:=p;
  1677. last:=p;
  1678. p.FListNext:=nil;
  1679. end;
  1680. {****************************************************************************
  1681. tindexarray
  1682. ****************************************************************************}
  1683. constructor tindexarray.create(Agrowsize:integer);
  1684. begin
  1685. growsize:=Agrowsize;
  1686. size:=0;
  1687. count:=0;
  1688. data:=nil;
  1689. First:=nil;
  1690. noclear:=false;
  1691. end;
  1692. destructor tindexarray.destroy;
  1693. begin
  1694. if assigned(data) then
  1695. begin
  1696. if not noclear then
  1697. clear;
  1698. freemem(data);
  1699. data:=nil;
  1700. end;
  1701. end;
  1702. function tindexarray.search(nr:integer):TNamedIndexItem;
  1703. begin
  1704. if nr<=count then
  1705. search:=data^[nr]
  1706. else
  1707. search:=nil;
  1708. end;
  1709. procedure tindexarray.clear;
  1710. var
  1711. i : integer;
  1712. begin
  1713. for i:=1 to count do
  1714. if assigned(data^[i]) then
  1715. begin
  1716. data^[i].free;
  1717. data^[i]:=nil;
  1718. end;
  1719. count:=0;
  1720. First:=nil;
  1721. end;
  1722. procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
  1723. var
  1724. i : integer;
  1725. begin
  1726. for i:=1 to count do
  1727. if assigned(data^[i]) then
  1728. proc2call(data^[i],arg);
  1729. end;
  1730. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  1731. var
  1732. i : integer;
  1733. begin
  1734. for i:=1 to count do
  1735. if assigned(data^[i]) then
  1736. proc2call(data^[i],arg);
  1737. end;
  1738. procedure tindexarray.grow(gsize:integer);
  1739. var
  1740. osize : integer;
  1741. begin
  1742. osize:=size;
  1743. inc(size,gsize);
  1744. reallocmem(data,size*sizeof(pointer));
  1745. fillchar(data^[osize+1],gsize*sizeof(pointer),0);
  1746. end;
  1747. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  1748. var
  1749. i : integer;
  1750. begin
  1751. i:=p.Findexnr;
  1752. { update counter }
  1753. if i=count then
  1754. dec(count);
  1755. { update Linked List }
  1756. while (i>0) do
  1757. begin
  1758. dec(i);
  1759. if (i>0) and assigned(data^[i]) then
  1760. begin
  1761. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  1762. break;
  1763. end;
  1764. end;
  1765. if i=0 then
  1766. First:=p.FindexNext;
  1767. data^[p.FIndexnr]:=nil;
  1768. { clear entry }
  1769. p.FIndexnr:=-1;
  1770. p.FIndexNext:=nil;
  1771. end;
  1772. procedure tindexarray.delete(var p:TNamedIndexItem);
  1773. begin
  1774. deleteindex(p);
  1775. p.free;
  1776. p:=nil;
  1777. end;
  1778. procedure tindexarray.insert(p:TNamedIndexItem);
  1779. var
  1780. i : integer;
  1781. begin
  1782. if p.FIndexnr=-1 then
  1783. begin
  1784. inc(count);
  1785. p.FIndexnr:=count;
  1786. end;
  1787. if p.FIndexnr>count then
  1788. count:=p.FIndexnr;
  1789. if count>size then
  1790. grow(((count div growsize)+1)*growsize);
  1791. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  1792. data^[p.FIndexnr]:=p;
  1793. { update Linked List backward }
  1794. i:=p.FIndexnr;
  1795. while (i>0) do
  1796. begin
  1797. dec(i);
  1798. if (i>0) and assigned(data^[i]) then
  1799. begin
  1800. data^[i].FIndexNext:=p;
  1801. break;
  1802. end;
  1803. end;
  1804. if i=0 then
  1805. First:=p;
  1806. { update Linked List forward }
  1807. i:=p.FIndexnr;
  1808. while (i<=count) do
  1809. begin
  1810. inc(i);
  1811. if (i<=count) and assigned(data^[i]) then
  1812. begin
  1813. p.FIndexNext:=data^[i];
  1814. exit;
  1815. end;
  1816. end;
  1817. if i>count then
  1818. p.FIndexNext:=nil;
  1819. end;
  1820. procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
  1821. var
  1822. i : integer;
  1823. begin
  1824. newp.FIndexnr:=oldp.FIndexnr;
  1825. newp.FIndexNext:=oldp.FIndexNext;
  1826. data^[newp.FIndexnr]:=newp;
  1827. if First=oldp then
  1828. First:=newp;
  1829. { update Linked List backward }
  1830. i:=newp.FIndexnr;
  1831. while (i>0) do
  1832. begin
  1833. dec(i);
  1834. if (i>0) and assigned(data^[i]) then
  1835. begin
  1836. data^[i].FIndexNext:=newp;
  1837. break;
  1838. end;
  1839. end;
  1840. end;
  1841. {****************************************************************************
  1842. tdynamicarray
  1843. ****************************************************************************}
  1844. constructor tdynamicarray.create(Ablocksize:integer);
  1845. begin
  1846. FPosn:=0;
  1847. FPosnblock:=nil;
  1848. FFirstblock:=nil;
  1849. FLastblock:=nil;
  1850. Fblocksize:=Ablocksize;
  1851. grow;
  1852. end;
  1853. destructor tdynamicarray.destroy;
  1854. var
  1855. hp : pdynamicblock;
  1856. begin
  1857. while assigned(FFirstblock) do
  1858. begin
  1859. hp:=FFirstblock;
  1860. FFirstblock:=FFirstblock^.Next;
  1861. Freemem(hp);
  1862. end;
  1863. end;
  1864. function tdynamicarray.size:integer;
  1865. begin
  1866. if assigned(FLastblock) then
  1867. size:=FLastblock^.pos+FLastblock^.used
  1868. else
  1869. size:=0;
  1870. end;
  1871. procedure tdynamicarray.reset;
  1872. var
  1873. hp : pdynamicblock;
  1874. begin
  1875. while assigned(FFirstblock) do
  1876. begin
  1877. hp:=FFirstblock;
  1878. FFirstblock:=FFirstblock^.Next;
  1879. Freemem(hp);
  1880. end;
  1881. FPosn:=0;
  1882. FPosnblock:=nil;
  1883. FFirstblock:=nil;
  1884. FLastblock:=nil;
  1885. grow;
  1886. end;
  1887. procedure tdynamicarray.grow;
  1888. var
  1889. nblock : pdynamicblock;
  1890. begin
  1891. Getmem(nblock,blocksize+dynamicblockbasesize);
  1892. if not assigned(FFirstblock) then
  1893. begin
  1894. FFirstblock:=nblock;
  1895. FPosnblock:=nblock;
  1896. nblock^.pos:=0;
  1897. end
  1898. else
  1899. begin
  1900. FLastblock^.Next:=nblock;
  1901. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1902. end;
  1903. nblock^.used:=0;
  1904. nblock^.Next:=nil;
  1905. fillchar(nblock^.data,blocksize,0);
  1906. FLastblock:=nblock;
  1907. end;
  1908. procedure tdynamicarray.align(i:integer);
  1909. var
  1910. j : integer;
  1911. begin
  1912. j:=(FPosn mod i);
  1913. if j<>0 then
  1914. begin
  1915. j:=i-j;
  1916. if FPosnblock^.used+j>blocksize then
  1917. begin
  1918. dec(j,blocksize-FPosnblock^.used);
  1919. FPosnblock^.used:=blocksize;
  1920. grow;
  1921. FPosnblock:=FLastblock;
  1922. end;
  1923. inc(FPosnblock^.used,j);
  1924. inc(FPosn,j);
  1925. end;
  1926. end;
  1927. procedure tdynamicarray.seek(i:integer);
  1928. begin
  1929. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  1930. begin
  1931. { set FPosnblock correct if the size is bigger then
  1932. the current block }
  1933. if FPosnblock^.pos>i then
  1934. FPosnblock:=FFirstblock;
  1935. while assigned(FPosnblock) do
  1936. begin
  1937. if FPosnblock^.pos+blocksize>i then
  1938. break;
  1939. FPosnblock:=FPosnblock^.Next;
  1940. end;
  1941. { not found ? then increase blocks }
  1942. if not assigned(FPosnblock) then
  1943. begin
  1944. repeat
  1945. { the current FLastblock is now also fully used }
  1946. FLastblock^.used:=blocksize;
  1947. grow;
  1948. FPosnblock:=FLastblock;
  1949. until FPosnblock^.pos+blocksize>=i;
  1950. end;
  1951. end;
  1952. FPosn:=i;
  1953. if FPosn mod blocksize>FPosnblock^.used then
  1954. FPosnblock^.used:=FPosn mod blocksize;
  1955. end;
  1956. procedure tdynamicarray.write(const d;len:integer);
  1957. var
  1958. p : pchar;
  1959. i,j : integer;
  1960. begin
  1961. p:=pchar(@d);
  1962. while (len>0) do
  1963. begin
  1964. i:=FPosn mod blocksize;
  1965. if i+len>=blocksize then
  1966. begin
  1967. j:=blocksize-i;
  1968. move(p^,FPosnblock^.data[i],j);
  1969. inc(p,j);
  1970. inc(FPosn,j);
  1971. dec(len,j);
  1972. FPosnblock^.used:=blocksize;
  1973. if assigned(FPosnblock^.Next) then
  1974. FPosnblock:=FPosnblock^.Next
  1975. else
  1976. begin
  1977. grow;
  1978. FPosnblock:=FLastblock;
  1979. end;
  1980. end
  1981. else
  1982. begin
  1983. move(p^,FPosnblock^.data[i],len);
  1984. inc(p,len);
  1985. inc(FPosn,len);
  1986. i:=FPosn mod blocksize;
  1987. if i>FPosnblock^.used then
  1988. FPosnblock^.used:=i;
  1989. len:=0;
  1990. end;
  1991. end;
  1992. end;
  1993. procedure tdynamicarray.writestr(const s:string);
  1994. begin
  1995. write(s[1],length(s));
  1996. end;
  1997. function tdynamicarray.read(var d;len:integer):integer;
  1998. var
  1999. p : pchar;
  2000. i,j,res : integer;
  2001. begin
  2002. res:=0;
  2003. p:=pchar(@d);
  2004. while (len>0) do
  2005. begin
  2006. i:=FPosn mod blocksize;
  2007. if i+len>=FPosnblock^.used then
  2008. begin
  2009. j:=FPosnblock^.used-i;
  2010. move(FPosnblock^.data[i],p^,j);
  2011. inc(p,j);
  2012. inc(FPosn,j);
  2013. inc(res,j);
  2014. dec(len,j);
  2015. if assigned(FPosnblock^.Next) then
  2016. FPosnblock:=FPosnblock^.Next
  2017. else
  2018. break;
  2019. end
  2020. else
  2021. begin
  2022. move(FPosnblock^.data[i],p^,len);
  2023. inc(p,len);
  2024. inc(FPosn,len);
  2025. inc(res,len);
  2026. len:=0;
  2027. end;
  2028. end;
  2029. read:=res;
  2030. end;
  2031. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  2032. var
  2033. i,left : integer;
  2034. begin
  2035. if maxlen=-1 then
  2036. maxlen:=maxlongint;
  2037. repeat
  2038. left:=blocksize-FPosnblock^.used;
  2039. if left>maxlen then
  2040. left:=maxlen;
  2041. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  2042. dec(maxlen,i);
  2043. inc(FPosnblock^.used,i);
  2044. if FPosnblock^.used=blocksize then
  2045. begin
  2046. if assigned(FPosnblock^.Next) then
  2047. FPosnblock:=FPosnblock^.Next
  2048. else
  2049. begin
  2050. grow;
  2051. FPosnblock:=FLastblock;
  2052. end;
  2053. end;
  2054. until (i<left) or (maxlen=0);
  2055. end;
  2056. procedure tdynamicarray.writestream(f:TCStream);
  2057. var
  2058. hp : pdynamicblock;
  2059. begin
  2060. hp:=FFirstblock;
  2061. while assigned(hp) do
  2062. begin
  2063. f.Write(hp^.data,hp^.used);
  2064. hp:=hp^.Next;
  2065. end;
  2066. end;
  2067. {****************************************************************************
  2068. TLinkStrMap
  2069. ****************************************************************************}
  2070. Constructor TLinkStrMap.create;
  2071. begin
  2072. inherited;
  2073. itemcnt:=0;
  2074. end;
  2075. procedure TLinkStrMap.Add(key:ansistring;value:AnsiString='';weight:longint=weightdefault);
  2076. begin
  2077. if lookup(key)<>-1 Then
  2078. exit;
  2079. if itemcnt<=length(fmap) Then
  2080. setlength(fmap,itemcnt+10);
  2081. fmap[itemcnt].key:=key;
  2082. fmap[itemcnt].value:=value;
  2083. fmap[itemcnt].weight:=weight;
  2084. inc(itemcnt);
  2085. end;
  2086. function TLinkStrMap.AddDep(keyvalue:String):boolean;
  2087. var i : Longint;
  2088. begin
  2089. AddDep:=false;
  2090. i:=pos('=',keyvalue);
  2091. if i=0 then
  2092. exit;
  2093. Add(Copy(KeyValue,1,i-1),Copy(KeyValue,i+1,length(KeyValue)-i));
  2094. AddDep:=True;
  2095. end;
  2096. function TLinkStrMap.AddWeight(keyvalue:String):boolean;
  2097. var i,j : Longint;
  2098. Code : Word;
  2099. s : AnsiString;
  2100. begin
  2101. AddWeight:=false;
  2102. i:=pos('=',keyvalue);
  2103. if i=0 then
  2104. exit;
  2105. s:=Copy(KeyValue,i+1,length(KeyValue)-i);
  2106. val(s,j,code);
  2107. if code=0 Then
  2108. begin
  2109. Add(Copy(KeyValue,1,i-1),'',j);
  2110. AddWeight:=True;
  2111. end;
  2112. end;
  2113. procedure TLinkStrMap.addseries(keys:AnsiString;weight:longint);
  2114. var i,j,k : longint;
  2115. begin
  2116. k:=length(keys);
  2117. i:=1;
  2118. while i<=k do
  2119. begin
  2120. j:=i;
  2121. while (i<=k) and (keys[i]<>',') do
  2122. inc(i);
  2123. add(copy(keys,j,i-j),'',weight);
  2124. inc(i);
  2125. end;
  2126. end;
  2127. procedure TLinkStrMap.SetValue(Key:Ansistring;weight:Integer);
  2128. var j : longint;
  2129. begin
  2130. j:=lookup(key);
  2131. if j<>-1 then
  2132. fmap[j].weight:=weight;
  2133. end;
  2134. function TLinkStrMap.find(key:Ansistring):Ansistring;
  2135. var j : longint;
  2136. begin
  2137. find:='';
  2138. j:=lookup(key);
  2139. if j<>-1 then
  2140. find:=fmap[j].value;
  2141. end;
  2142. function TLinkStrMap.lookup(key:Ansistring):longint;
  2143. var i : longint;
  2144. begin
  2145. lookup:=-1;
  2146. i:=0;
  2147. {$B-}
  2148. while (i<itemcnt) and (fmap[i].key<>key) do
  2149. inc(i);
  2150. {$B+}
  2151. if i<>itemcnt then
  2152. lookup:=i;
  2153. end;
  2154. procedure TLinkStrMap.SortOnWeight;
  2155. var i, j : longint;
  2156. m : TLinkRec;
  2157. begin
  2158. if itemcnt <2 then exit;
  2159. for i:=0 to itemcnt-1 do
  2160. for j:=i+1 to itemcnt-1 do
  2161. begin
  2162. if fmap[i].weight>fmap[j].weight Then
  2163. begin
  2164. m:=fmap[i];
  2165. fmap[i]:=fmap[j];
  2166. fmap[j]:=m;
  2167. end;
  2168. end;
  2169. end;
  2170. function TLinkStrMap.getlinkrec(i:longint):TLinkRec;
  2171. begin
  2172. result:=fmap[i];
  2173. end;
  2174. procedure TLinkStrMap.Expand(Src:TStringList;Dest:TLinkStrMap);
  2175. // expands every thing in Src to Dest for linkorder purposes.
  2176. var l,r : longint;
  2177. LibN : String;
  2178. begin
  2179. while not src.empty do
  2180. begin
  2181. LibN:=src.getfirst;
  2182. r:=lookup (LibN);
  2183. if r=-1 then
  2184. dest.add(LibN)
  2185. else
  2186. dest.addseries(fmap[r].value);
  2187. end;
  2188. end;
  2189. procedure TLinkStrMap.UpdateWeights(Weightmap:TLinkStrMap);
  2190. var l,r : longint;
  2191. begin
  2192. for l := 0 to itemcnt-1 do
  2193. begin
  2194. r:=weightmap.lookup (fmap[l].key);
  2195. if r<>-1 then
  2196. fmap[l].weight:=weightmap[r].weight;
  2197. end;
  2198. end;
  2199. end.