cclasses.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
  4. This module provides some basic classes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cclasses;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cutils,cstreams;
  23. {********************************************
  24. TMemDebug
  25. ********************************************}
  26. type
  27. tmemdebug = class
  28. private
  29. totalmem,
  30. startmem : integer;
  31. infostr : string[40];
  32. public
  33. constructor Create(const s:string);
  34. destructor Destroy;override;
  35. procedure show;
  36. procedure start;
  37. procedure stop;
  38. end;
  39. {********************************************
  40. TLinkedList
  41. ********************************************}
  42. type
  43. TLinkedListItem = class
  44. public
  45. Previous,
  46. Next : TLinkedListItem;
  47. Constructor Create;
  48. Destructor Destroy;override;
  49. Function GetCopy:TLinkedListItem;virtual;
  50. end;
  51. TLinkedListItemClass = class of TLinkedListItem;
  52. TLinkedList = class
  53. private
  54. FCount : integer;
  55. FFirst,
  56. FLast : TLinkedListItem;
  57. FNoClear : boolean;
  58. public
  59. constructor Create;
  60. destructor Destroy;override;
  61. { true when the List is empty }
  62. function Empty:boolean;
  63. { deletes all Items }
  64. procedure Clear;
  65. { inserts an Item }
  66. procedure Insert(Item:TLinkedListItem);
  67. { inserts an Item before Loc }
  68. procedure InsertBefore(Item,Loc : TLinkedListItem);
  69. { inserts an Item after Loc }
  70. procedure InsertAfter(Item,Loc : TLinkedListItem);virtual;
  71. { concats an Item }
  72. procedure Concat(Item:TLinkedListItem);
  73. { deletes an Item }
  74. procedure Remove(Item:TLinkedListItem);
  75. { Gets First Item }
  76. function GetFirst:TLinkedListItem;
  77. { Gets last Item }
  78. function GetLast:TLinkedListItem;
  79. { inserts another List at the begin and make this List empty }
  80. procedure insertList(p : TLinkedList);
  81. { inserts another List after the provided item and make this List empty }
  82. procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  83. { concats another List at the end and make this List empty }
  84. procedure concatList(p : TLinkedList);
  85. { concats another List at the start and makes a copy
  86. the list is ordered in reverse.
  87. }
  88. procedure insertListcopy(p : TLinkedList);
  89. { concats another List at the end and makes a copy }
  90. procedure concatListcopy(p : TLinkedList);
  91. property First:TLinkedListItem read FFirst;
  92. property Last:TLinkedListItem read FLast;
  93. property Count:Integer read FCount;
  94. property NoClear:boolean write FNoClear;
  95. end;
  96. {********************************************
  97. TStringList
  98. ********************************************}
  99. { string containerItem }
  100. TStringListItem = class(TLinkedListItem)
  101. FPStr : PString;
  102. public
  103. constructor Create(const s:string);
  104. destructor Destroy;override;
  105. function GetCopy:TLinkedListItem;override;
  106. function Str:string;
  107. end;
  108. { string container }
  109. TStringList = class(TLinkedList)
  110. private
  111. FDoubles : boolean; { if this is set to true, doubles are allowed }
  112. public
  113. constructor Create;
  114. constructor Create_No_Double;
  115. { inserts an Item }
  116. procedure Insert(const s:string);
  117. { concats an Item }
  118. procedure Concat(const s:string);
  119. { deletes an Item }
  120. procedure Remove(const s:string);
  121. { Gets First Item }
  122. function GetFirst:string;
  123. { Gets last Item }
  124. function GetLast:string;
  125. { true if string is in the container }
  126. function Find(const s:string):TStringListItem;
  127. { inserts an item }
  128. procedure InsertItem(item:TStringListItem);
  129. { concats an item }
  130. procedure ConcatItem(item:TStringListItem);
  131. property Doubles:boolean read FDoubles write FDoubles;
  132. end;
  133. {********************************************
  134. Dictionary
  135. ********************************************}
  136. const
  137. { the real size will be [0..hasharray-1] ! }
  138. hasharraysize = 512;
  139. type
  140. { namedindexobect for use with dictionary and indexarray }
  141. TNamedIndexItem=class
  142. private
  143. { indexarray }
  144. FIndexNr : integer;
  145. FIndexNext : TNamedIndexItem;
  146. { dictionary }
  147. FLeft,
  148. FRight : TNamedIndexItem;
  149. FSpeedValue : cardinal;
  150. { singleList }
  151. FListNext : TNamedIndexItem;
  152. FName : Pstring;
  153. protected
  154. function GetName:string;virtual;
  155. procedure SetName(const n:string);virtual;
  156. public
  157. constructor Create;
  158. constructor CreateName(const n:string);
  159. destructor Destroy;override;
  160. property IndexNr:integer read FIndexNr write FIndexNr;
  161. property IndexNext:TNamedIndexItem read FIndexNext write FIndexNext;
  162. property Name:string read GetName write SetName;
  163. property SpeedValue:cardinal read FSpeedValue;
  164. property ListNext:TNamedIndexItem read FListNext;
  165. property Left:TNamedIndexItem read FLeft write FLeft;
  166. property Right:TNamedIndexItem read FRight write FRight;
  167. end;
  168. Pdictionaryhasharray=^Tdictionaryhasharray;
  169. Tdictionaryhasharray=array[0..hasharraysize-1] of TNamedIndexItem;
  170. TnamedIndexCallback = procedure(p:TNamedIndexItem;arg:pointer) of object;
  171. TnamedIndexStaticCallback = procedure(p:TNamedIndexItem;arg:pointer);
  172. Tdictionary=class
  173. private
  174. FRoot : TNamedIndexItem;
  175. FHashArray : Pdictionaryhasharray;
  176. procedure cleartree(var obj:TNamedIndexItem);
  177. function insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  178. procedure inserttree(currtree,currroot:TNamedIndexItem);
  179. public
  180. noclear : boolean;
  181. delete_doubles : boolean;
  182. constructor Create;
  183. destructor Destroy;override;
  184. procedure usehash;
  185. procedure clear;
  186. function delete(const s:string):TNamedIndexItem;
  187. function empty:boolean;
  188. procedure foreach(proc2call:TNamedIndexcallback;arg:pointer);
  189. procedure foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  190. function insert(obj:TNamedIndexItem):TNamedIndexItem;
  191. function replace(oldobj,newobj:TNamedIndexItem):boolean;
  192. function rename(const olds,News : string):TNamedIndexItem;
  193. function search(const s:string):TNamedIndexItem;
  194. function speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  195. property Items[const s:string]:TNamedIndexItem read Search;default;
  196. end;
  197. tsingleList=class
  198. First,
  199. last : TNamedIndexItem;
  200. constructor Create;
  201. procedure reset;
  202. procedure clear;
  203. procedure insert(p:TNamedIndexItem);
  204. end;
  205. tindexobjectarray=array[1..16000] of TNamedIndexItem;
  206. pnamedindexobjectarray=^tindexobjectarray;
  207. tindexarray=class
  208. noclear : boolean;
  209. First : TNamedIndexItem;
  210. count : integer;
  211. constructor Create(Agrowsize:integer);
  212. destructor destroy;override;
  213. procedure clear;
  214. procedure foreach(proc2call : Tnamedindexcallback;arg:pointer);
  215. procedure foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  216. procedure deleteindex(p:TNamedIndexItem);
  217. procedure delete(var p:TNamedIndexItem);
  218. procedure insert(p:TNamedIndexItem);
  219. procedure replace(oldp,newp:TNamedIndexItem);
  220. function search(nr:integer):TNamedIndexItem;
  221. private
  222. growsize,
  223. size : integer;
  224. data : pnamedindexobjectarray;
  225. procedure grow(gsize:integer);
  226. end;
  227. {********************************************
  228. DynamicArray
  229. ********************************************}
  230. const
  231. dynamicblockbasesize = 12;
  232. type
  233. pdynamicblock = ^tdynamicblock;
  234. tdynamicblock = record
  235. pos,
  236. used : integer;
  237. Next : pdynamicblock;
  238. { can't use sizeof(integer) because it crashes gdb }
  239. data : array[0..1024*1024] of byte;
  240. end;
  241. tdynamicarray = class
  242. private
  243. FPosn : integer;
  244. FPosnblock : pdynamicblock;
  245. FBlocksize : integer;
  246. FFirstblock,
  247. FLastblock : pdynamicblock;
  248. procedure grow;
  249. public
  250. constructor Create(Ablocksize:integer);
  251. destructor Destroy;override;
  252. procedure reset;
  253. function size:integer;
  254. procedure align(i:integer);
  255. procedure seek(i:integer);
  256. function read(var d;len:integer):integer;
  257. procedure write(const d;len:integer);
  258. procedure writestr(const s:string);
  259. procedure readstream(f:TCStream;maxlen:longint);
  260. procedure writestream(f:TCStream);
  261. property BlockSize : integer read FBlocksize;
  262. property FirstBlock : PDynamicBlock read FFirstBlock;
  263. property Pos : integer read FPosn;
  264. end;
  265. implementation
  266. {*****************************************************************************
  267. Memory debug
  268. *****************************************************************************}
  269. constructor tmemdebug.create(const s:string);
  270. begin
  271. infostr:=s;
  272. totalmem:=0;
  273. Start;
  274. end;
  275. procedure tmemdebug.start;
  276. begin
  277. {$ifdef Delphi}
  278. startmem:=0;
  279. {$else}
  280. startmem:=memavail;
  281. {$endif Delphi}
  282. end;
  283. procedure tmemdebug.stop;
  284. begin
  285. if startmem<>0 then
  286. begin
  287. {$ifndef Delphi}
  288. inc(TotalMem,memavail-startmem);
  289. {$endif}
  290. startmem:=0;
  291. end;
  292. end;
  293. destructor tmemdebug.destroy;
  294. begin
  295. Stop;
  296. show;
  297. end;
  298. procedure tmemdebug.show;
  299. begin
  300. {$ifndef Delphi}
  301. write('memory [',infostr,'] ');
  302. if TotalMem>0 then
  303. writeln(DStr(TotalMem shr 10),' Kb released')
  304. else
  305. writeln(DStr((-TotalMem) shr 10),' Kb allocated');
  306. {$endif Delphi}
  307. end;
  308. {*****************************************************************************
  309. Stack
  310. *****************************************************************************}
  311. {$ifdef fixLeaksOnError}
  312. constructor TStack.init;
  313. begin
  314. head := nil;
  315. end;
  316. procedure TStack.push(p: pointer);
  317. var s: PStackItem;
  318. begin
  319. New(s);
  320. s^.data := p;
  321. s^.Next := head;
  322. head := s;
  323. end;
  324. function TStack.pop: pointer;
  325. var s: PStackItem;
  326. begin
  327. pop := top;
  328. if assigned(head) then
  329. begin
  330. s := head^.Next;
  331. dispose(head);
  332. head := s;
  333. end
  334. end;
  335. function TStack.top: pointer;
  336. begin
  337. if not isEmpty then
  338. top := head^.data
  339. else top := NIL;
  340. end;
  341. function TStack.isEmpty: boolean;
  342. begin
  343. isEmpty := head = nil;
  344. end;
  345. destructor TStack.done;
  346. var temp: PStackItem;
  347. begin
  348. while head <> nil do
  349. begin
  350. temp := head^.Next;
  351. dispose(head);
  352. head := temp;
  353. end;
  354. end;
  355. {$endif fixLeaksOnError}
  356. {****************************************************************************
  357. TLinkedListItem
  358. ****************************************************************************}
  359. constructor TLinkedListItem.Create;
  360. begin
  361. Previous:=nil;
  362. Next:=nil;
  363. end;
  364. destructor TLinkedListItem.Destroy;
  365. begin
  366. end;
  367. function TLinkedListItem.GetCopy:TLinkedListItem;
  368. var
  369. p : TLinkedListItem;
  370. l : integer;
  371. begin
  372. p:=TLinkedListItemClass(ClassType).Create;
  373. l:=InstanceSize;
  374. Move(pointer(self)^,pointer(p)^,l);
  375. Result:=p;
  376. end;
  377. {****************************************************************************
  378. TLinkedList
  379. ****************************************************************************}
  380. constructor TLinkedList.Create;
  381. begin
  382. FFirst:=nil;
  383. Flast:=nil;
  384. FCount:=0;
  385. FNoClear:=False;
  386. end;
  387. destructor TLinkedList.destroy;
  388. begin
  389. if not FNoClear then
  390. Clear;
  391. end;
  392. function TLinkedList.empty:boolean;
  393. begin
  394. Empty:=(FFirst=nil);
  395. end;
  396. procedure TLinkedList.Insert(Item:TLinkedListItem);
  397. begin
  398. if FFirst=nil then
  399. begin
  400. FLast:=Item;
  401. Item.Previous:=nil;
  402. Item.Next:=nil;
  403. end
  404. else
  405. begin
  406. FFirst.Previous:=Item;
  407. Item.Previous:=nil;
  408. Item.Next:=FFirst;
  409. end;
  410. FFirst:=Item;
  411. inc(FCount);
  412. end;
  413. procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
  414. begin
  415. Item.Previous:=Loc.Previous;
  416. Item.Next:=Loc;
  417. Loc.Previous:=Item;
  418. if assigned(Item.Previous) then
  419. Item.Previous.Next:=Item
  420. else
  421. { if we've no next item, we've to adjust FFist }
  422. FFirst:=Item;
  423. inc(FCount);
  424. end;
  425. procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
  426. begin
  427. Item.Next:=Loc.Next;
  428. Loc.Next:=Item;
  429. Item.Previous:=Loc;
  430. if assigned(Item.Next) then
  431. Item.Next.Previous:=Item
  432. else
  433. { if we've no next item, we've to adjust FLast }
  434. FLast:=Item;
  435. inc(FCount);
  436. end;
  437. procedure TLinkedList.Concat(Item:TLinkedListItem);
  438. begin
  439. if FFirst=nil then
  440. begin
  441. FFirst:=Item;
  442. Item.Previous:=nil;
  443. Item.Next:=nil;
  444. end
  445. else
  446. begin
  447. Flast.Next:=Item;
  448. Item.Previous:=Flast;
  449. Item.Next:=nil;
  450. end;
  451. Flast:=Item;
  452. inc(FCount);
  453. end;
  454. procedure TLinkedList.remove(Item:TLinkedListItem);
  455. begin
  456. if Item=nil then
  457. exit;
  458. if (FFirst=Item) and (Flast=Item) then
  459. begin
  460. FFirst:=nil;
  461. Flast:=nil;
  462. end
  463. else if FFirst=Item then
  464. begin
  465. FFirst:=Item.Next;
  466. if assigned(FFirst) then
  467. FFirst.Previous:=nil;
  468. end
  469. else if Flast=Item then
  470. begin
  471. Flast:=Flast.Previous;
  472. if assigned(Flast) then
  473. Flast.Next:=nil;
  474. end
  475. else
  476. begin
  477. Item.Previous.Next:=Item.Next;
  478. Item.Next.Previous:=Item.Previous;
  479. end;
  480. Item.Next:=nil;
  481. Item.Previous:=nil;
  482. dec(FCount);
  483. end;
  484. procedure TLinkedList.clear;
  485. var
  486. NewNode : TLinkedListItem;
  487. begin
  488. NewNode:=FFirst;
  489. while assigned(NewNode) do
  490. begin
  491. FFirst:=NewNode.Next;
  492. NewNode.Free;
  493. NewNode:=FFirst;
  494. end;
  495. FLast:=nil;
  496. FFirst:=nil;
  497. FCount:=0;
  498. end;
  499. function TLinkedList.GetFirst:TLinkedListItem;
  500. begin
  501. if FFirst=nil then
  502. GetFirst:=nil
  503. else
  504. begin
  505. GetFirst:=FFirst;
  506. if FFirst=FLast then
  507. FLast:=nil;
  508. FFirst:=FFirst.Next;
  509. dec(FCount);
  510. end;
  511. end;
  512. function TLinkedList.GetLast:TLinkedListItem;
  513. begin
  514. if FLast=nil then
  515. Getlast:=nil
  516. else
  517. begin
  518. Getlast:=FLast;
  519. if FLast=FFirst then
  520. FFirst:=nil;
  521. FLast:=FLast.Previous;
  522. dec(FCount);
  523. end;
  524. end;
  525. procedure TLinkedList.insertList(p : TLinkedList);
  526. begin
  527. { empty List ? }
  528. if (p.FFirst=nil) then
  529. exit;
  530. p.Flast.Next:=FFirst;
  531. { we have a double Linked List }
  532. if assigned(FFirst) then
  533. FFirst.Previous:=p.Flast;
  534. FFirst:=p.FFirst;
  535. if (FLast=nil) then
  536. Flast:=p.Flast;
  537. { p becomes empty }
  538. p.FFirst:=nil;
  539. p.Flast:=nil;
  540. end;
  541. procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  542. begin
  543. { empty List ? }
  544. if (p.FFirst=nil) then
  545. exit;
  546. if (Item=nil) then
  547. begin
  548. { Insert at begin }
  549. InsertList(p);
  550. exit;
  551. end
  552. else
  553. begin
  554. p.FFirst.Previous:=Item;
  555. p.FLast.Next:=Item.Next;
  556. if assigned(Item.Next) then
  557. Item.Next.Previous:=p.FLast
  558. else
  559. FLast:=p.FLast;
  560. Item.Next:=p.FFirst;
  561. end;
  562. { p becomes empty }
  563. p.FFirst:=nil;
  564. p.Flast:=nil;
  565. end;
  566. procedure TLinkedList.concatList(p : TLinkedList);
  567. begin
  568. if (p.FFirst=nil) then
  569. exit;
  570. if FFirst=nil then
  571. FFirst:=p.FFirst
  572. else
  573. begin
  574. FLast.Next:=p.FFirst;
  575. p.FFirst.Previous:=Flast;
  576. end;
  577. Flast:=p.Flast;
  578. { make p empty }
  579. p.Flast:=nil;
  580. p.FFirst:=nil;
  581. end;
  582. procedure TLinkedList.insertListcopy(p : TLinkedList);
  583. var
  584. NewNode,NewNode2 : TLinkedListItem;
  585. begin
  586. NewNode:=p.First;
  587. while assigned(NewNode) do
  588. begin
  589. NewNode2:=NewNode.Getcopy;
  590. if assigned(NewNode2) then
  591. Insert(NewNode2);
  592. NewNode:=NewNode.Next;
  593. end;
  594. end;
  595. procedure TLinkedList.concatListcopy(p : TLinkedList);
  596. var
  597. NewNode,NewNode2 : TLinkedListItem;
  598. begin
  599. NewNode:=p.First;
  600. while assigned(NewNode) do
  601. begin
  602. NewNode2:=NewNode.Getcopy;
  603. if assigned(NewNode2) then
  604. Concat(NewNode2);
  605. NewNode:=NewNode.Next;
  606. end;
  607. end;
  608. {****************************************************************************
  609. TStringListItem
  610. ****************************************************************************}
  611. constructor TStringListItem.Create(const s:string);
  612. begin
  613. inherited Create;
  614. FPStr:=stringdup(s);
  615. end;
  616. destructor TStringListItem.Destroy;
  617. begin
  618. stringdispose(FPStr);
  619. end;
  620. function TStringListItem.Str:string;
  621. begin
  622. Str:=FPStr^;
  623. end;
  624. function TStringListItem.GetCopy:TLinkedListItem;
  625. begin
  626. Result:=(inherited GetCopy);
  627. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  628. end;
  629. {****************************************************************************
  630. TSTRINGList
  631. ****************************************************************************}
  632. constructor tstringList.Create;
  633. begin
  634. inherited Create;
  635. FDoubles:=true;
  636. end;
  637. constructor tstringList.Create_no_double;
  638. begin
  639. inherited Create;
  640. FDoubles:=false;
  641. end;
  642. procedure tstringList.insert(const s : string);
  643. begin
  644. if (s='') or
  645. ((not FDoubles) and (find(s)<>nil)) then
  646. exit;
  647. inherited insert(tstringListItem.create(s));
  648. end;
  649. procedure tstringList.concat(const s : string);
  650. begin
  651. if (s='') or
  652. ((not FDoubles) and (find(s)<>nil)) then
  653. exit;
  654. inherited concat(tstringListItem.create(s));
  655. end;
  656. procedure tstringList.remove(const s : string);
  657. var
  658. p : tstringListItem;
  659. begin
  660. if s='' then
  661. exit;
  662. p:=find(s);
  663. if assigned(p) then
  664. begin
  665. inherited Remove(p);
  666. p.Free;
  667. end;
  668. end;
  669. function tstringList.GetFirst : string;
  670. var
  671. p : tstringListItem;
  672. begin
  673. p:=tstringListItem(inherited GetFirst);
  674. if p=nil then
  675. GetFirst:=''
  676. else
  677. begin
  678. GetFirst:=p.FPStr^;
  679. p.free;
  680. end;
  681. end;
  682. function tstringList.Getlast : string;
  683. var
  684. p : tstringListItem;
  685. begin
  686. p:=tstringListItem(inherited Getlast);
  687. if p=nil then
  688. Getlast:=''
  689. else
  690. begin
  691. Getlast:=p.FPStr^;
  692. p.free;
  693. end;
  694. end;
  695. function tstringList.find(const s:string):TstringListItem;
  696. var
  697. NewNode : tstringListItem;
  698. begin
  699. find:=nil;
  700. if s='' then
  701. exit;
  702. NewNode:=tstringListItem(FFirst);
  703. while assigned(NewNode) do
  704. begin
  705. if NewNode.FPStr^=s then
  706. begin
  707. find:=NewNode;
  708. exit;
  709. end;
  710. NewNode:=tstringListItem(NewNode.Next);
  711. end;
  712. end;
  713. procedure TStringList.InsertItem(item:TStringListItem);
  714. begin
  715. inherited Insert(item);
  716. end;
  717. procedure TStringList.ConcatItem(item:TStringListItem);
  718. begin
  719. inherited Concat(item);
  720. end;
  721. {****************************************************************************
  722. TNamedIndexItem
  723. ****************************************************************************}
  724. constructor TNamedIndexItem.Create;
  725. begin
  726. { index }
  727. Findexnr:=-1;
  728. FindexNext:=nil;
  729. { dictionary }
  730. Fleft:=nil;
  731. Fright:=nil;
  732. FName:=nil;
  733. Fspeedvalue:=cardinal($ffffffff);
  734. { List }
  735. FListNext:=nil;
  736. end;
  737. constructor TNamedIndexItem.Createname(const n:string);
  738. begin
  739. { index }
  740. Findexnr:=-1;
  741. FindexNext:=nil;
  742. { dictionary }
  743. Fleft:=nil;
  744. Fright:=nil;
  745. fspeedvalue:=getspeedvalue(n);
  746. {$ifdef compress}
  747. FName:=stringdup(minilzw_encode(n));
  748. {$else}
  749. FName:=stringdup(n);
  750. {$endif}
  751. { List }
  752. FListNext:=nil;
  753. end;
  754. destructor TNamedIndexItem.destroy;
  755. begin
  756. stringdispose(FName);
  757. end;
  758. procedure TNamedIndexItem.setname(const n:string);
  759. begin
  760. if speedvalue=cardinal($ffffffff) then
  761. begin
  762. if assigned(FName) then
  763. stringdispose(FName);
  764. fspeedvalue:=getspeedvalue(n);
  765. {$ifdef compress}
  766. FName:=stringdup(minilzw_encode(n));
  767. {$else}
  768. FName:=stringdup(n);
  769. {$endif}
  770. end;
  771. end;
  772. function TNamedIndexItem.GetName:string;
  773. begin
  774. if assigned(FName) then
  775. {$ifdef compress}
  776. Getname:=minilzw_decode(FName^)
  777. {$else}
  778. Getname:=FName^
  779. {$endif}
  780. else
  781. Getname:='';
  782. end;
  783. {****************************************************************************
  784. TDICTIONARY
  785. ****************************************************************************}
  786. constructor Tdictionary.Create;
  787. begin
  788. FRoot:=nil;
  789. FHashArray:=nil;
  790. noclear:=false;
  791. delete_doubles:=false;
  792. end;
  793. procedure Tdictionary.usehash;
  794. begin
  795. if not(assigned(FRoot)) and
  796. not(assigned(FHashArray)) then
  797. begin
  798. New(FHashArray);
  799. fillchar(FHashArray^,sizeof(FHashArray^),0);
  800. end;
  801. end;
  802. function counttree(p: tnamedindexitem): longint;
  803. begin
  804. counttree:=0;
  805. if not assigned(p) then
  806. exit;
  807. result := 1;
  808. inc(result,counttree(p.fleft));
  809. inc(result,counttree(p.fright));
  810. end;
  811. destructor Tdictionary.destroy;
  812. begin
  813. if not noclear then
  814. clear;
  815. if assigned(FHashArray) then
  816. begin
  817. dispose(FHashArray);
  818. end;
  819. end;
  820. procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
  821. begin
  822. if assigned(obj.Fleft) then
  823. cleartree(obj.FLeft);
  824. if assigned(obj.FRight) then
  825. cleartree(obj.FRight);
  826. obj.free;
  827. obj:=nil;
  828. end;
  829. procedure Tdictionary.clear;
  830. var
  831. w : integer;
  832. begin
  833. if assigned(FRoot) then
  834. cleartree(FRoot);
  835. if assigned(FHashArray) then
  836. for w:= low(FHashArray^) to high(FHashArray^) do
  837. if assigned(FHashArray^[w]) then
  838. cleartree(FHashArray^[w]);
  839. end;
  840. function Tdictionary.delete(const s:string):TNamedIndexItem;
  841. var
  842. p,SpeedValue : cardinal;
  843. n : TNamedIndexItem;
  844. {$ifdef compress}
  845. senc:string;
  846. {$else}
  847. senc:string absolute s;
  848. {$endif}
  849. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  850. begin
  851. while root.FRight<>nil do
  852. root:=root.FRight;
  853. root.FRight:=Atree;
  854. end;
  855. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  856. type
  857. leftright=(left,right);
  858. var
  859. lr : leftright;
  860. oldroot : TNamedIndexItem;
  861. begin
  862. oldroot:=nil;
  863. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  864. begin
  865. oldroot:=root;
  866. if SpeedValue<root.SpeedValue then
  867. begin
  868. root:=root.FRight;
  869. lr:=right;
  870. end
  871. else
  872. begin
  873. root:=root.FLeft;
  874. lr:=left;
  875. end;
  876. end;
  877. while (root<>nil) and (root.FName^<>senc) do
  878. begin
  879. oldroot:=root;
  880. if senc<root.FName^ then
  881. begin
  882. root:=root.FRight;
  883. lr:=right;
  884. end
  885. else
  886. begin
  887. root:=root.FLeft;
  888. lr:=left;
  889. end;
  890. end;
  891. if root.FLeft<>nil then
  892. begin
  893. { Now the Node pointing to root must point to the left
  894. subtree of root. The right subtree of root must be
  895. connected to the right bottom of the left subtree.}
  896. if lr=left then
  897. oldroot.FLeft:=root.FLeft
  898. else
  899. oldroot.FRight:=root.FLeft;
  900. if root.FRight<>nil then
  901. insert_right_bottom(root.FLeft,root.FRight);
  902. end
  903. else
  904. begin
  905. { There is no left subtree. So we can just replace the Node to
  906. delete with the right subtree.}
  907. if lr=left then
  908. oldroot.FLeft:=root.FRight
  909. else
  910. oldroot.FRight:=root.FRight;
  911. end;
  912. delete_from_tree:=root;
  913. end;
  914. begin
  915. {$ifdef compress}
  916. senc:=minilzw_encode(s);
  917. {$endif}
  918. SpeedValue:=GetSpeedValue(s);
  919. n:=FRoot;
  920. if assigned(FHashArray) then
  921. begin
  922. { First, check if the Node to delete directly located under
  923. the hasharray.}
  924. p:=SpeedValue mod hasharraysize;
  925. n:=FHashArray^[p];
  926. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  927. (n.FName^=senc) then
  928. begin
  929. { The Node to delete is directly located under the
  930. hasharray. Make the hasharray point to the left
  931. subtree of the Node and place the right subtree on
  932. the right-bottom of the left subtree.}
  933. if n.FLeft<>nil then
  934. begin
  935. FHashArray^[p]:=n.FLeft;
  936. if n.FRight<>nil then
  937. insert_right_bottom(n.FLeft,n.FRight);
  938. end
  939. else
  940. FHashArray^[p]:=n.FRight;
  941. delete:=n;
  942. exit;
  943. end;
  944. end
  945. else
  946. begin
  947. { First check if the Node to delete is the root.}
  948. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  949. (n.FName^=senc) then
  950. begin
  951. if n.FLeft<>nil then
  952. begin
  953. FRoot:=n.FLeft;
  954. if n.FRight<>nil then
  955. insert_right_bottom(n.FLeft,n.FRight);
  956. end
  957. else
  958. FRoot:=n.FRight;
  959. delete:=n;
  960. exit;
  961. end;
  962. end;
  963. delete:=delete_from_tree(n);
  964. end;
  965. function Tdictionary.empty:boolean;
  966. var
  967. w : integer;
  968. begin
  969. if assigned(FHashArray) then
  970. begin
  971. empty:=false;
  972. for w:=low(FHashArray^) to high(FHashArray^) do
  973. if assigned(FHashArray^[w]) then
  974. exit;
  975. empty:=true;
  976. end
  977. else
  978. empty:=(FRoot=nil);
  979. end;
  980. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
  981. procedure a(p:TNamedIndexItem;arg:pointer);
  982. begin
  983. proc2call(p,arg);
  984. if assigned(p.FLeft) then
  985. a(p.FLeft,arg);
  986. if assigned(p.FRight) then
  987. a(p.FRight,arg);
  988. end;
  989. var
  990. i : integer;
  991. begin
  992. if assigned(FHashArray) then
  993. begin
  994. for i:=low(FHashArray^) to high(FHashArray^) do
  995. if assigned(FHashArray^[i]) then
  996. a(FHashArray^[i],arg);
  997. end
  998. else
  999. if assigned(FRoot) then
  1000. a(FRoot,arg);
  1001. end;
  1002. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  1003. procedure a(p:TNamedIndexItem;arg:pointer);
  1004. begin
  1005. proc2call(p,arg);
  1006. if assigned(p.FLeft) then
  1007. a(p.FLeft,arg);
  1008. if assigned(p.FRight) then
  1009. a(p.FRight,arg);
  1010. end;
  1011. var
  1012. i : integer;
  1013. begin
  1014. if assigned(FHashArray) then
  1015. begin
  1016. for i:=low(FHashArray^) to high(FHashArray^) do
  1017. if assigned(FHashArray^[i]) then
  1018. a(FHashArray^[i],arg);
  1019. end
  1020. else
  1021. if assigned(FRoot) then
  1022. a(FRoot,arg);
  1023. end;
  1024. function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
  1025. var
  1026. hp : TNamedIndexItem;
  1027. begin
  1028. hp:=nil;
  1029. Replace:=false;
  1030. { newobj.FSpeedValue:=GetSpeedValue(newobj.FName^);}
  1031. { must be the same name and hash }
  1032. if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
  1033. (oldobj.FName^<>newobj.FName^) then
  1034. exit;
  1035. { copy tree info }
  1036. newobj.FLeft:=oldobj.FLeft;
  1037. newobj.FRight:=oldobj.FRight;
  1038. { update treeroot }
  1039. if assigned(FHashArray) then
  1040. begin
  1041. hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
  1042. if hp=oldobj then
  1043. begin
  1044. FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
  1045. hp:=nil;
  1046. end;
  1047. end
  1048. else
  1049. begin
  1050. hp:=FRoot;
  1051. if hp=oldobj then
  1052. begin
  1053. FRoot:=newobj;
  1054. hp:=nil;
  1055. end;
  1056. end;
  1057. { update parent entry }
  1058. while assigned(hp) do
  1059. begin
  1060. { is the node to replace the left or right, then
  1061. update this node and stop }
  1062. if hp.FLeft=oldobj then
  1063. begin
  1064. hp.FLeft:=newobj;
  1065. break;
  1066. end;
  1067. if hp.FRight=oldobj then
  1068. begin
  1069. hp.FRight:=newobj;
  1070. break;
  1071. end;
  1072. { First check SpeedValue, to allow a fast insert }
  1073. if hp.SpeedValue>oldobj.SpeedValue then
  1074. hp:=hp.FRight
  1075. else
  1076. if hp.SpeedValue<oldobj.SpeedValue then
  1077. hp:=hp.FLeft
  1078. else
  1079. begin
  1080. if (hp.FName^=oldobj.FName^) then
  1081. begin
  1082. { this can never happend, return error }
  1083. exit;
  1084. end
  1085. else
  1086. if oldobj.FName^>hp.FName^ then
  1087. hp:=hp.FLeft
  1088. else
  1089. hp:=hp.FRight;
  1090. end;
  1091. end;
  1092. Replace:=true;
  1093. end;
  1094. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  1095. begin
  1096. { obj.FSpeedValue:=GetSpeedValue(obj.FName^);}
  1097. if assigned(FHashArray) then
  1098. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  1099. else
  1100. insert:=insertNode(obj,FRoot);
  1101. end;
  1102. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  1103. begin
  1104. if currNode=nil then
  1105. begin
  1106. currNode:=NewNode;
  1107. insertNode:=NewNode;
  1108. end
  1109. { First check SpeedValue, to allow a fast insert }
  1110. else
  1111. if currNode.SpeedValue>NewNode.SpeedValue then
  1112. insertNode:=insertNode(NewNode,currNode.FRight)
  1113. else
  1114. if currNode.SpeedValue<NewNode.SpeedValue then
  1115. insertNode:=insertNode(NewNode,currNode.FLeft)
  1116. else
  1117. begin
  1118. if currNode.FName^>NewNode.FName^ then
  1119. insertNode:=insertNode(NewNode,currNode.FRight)
  1120. else
  1121. if currNode.FName^<NewNode.FName^ then
  1122. insertNode:=insertNode(NewNode,currNode.FLeft)
  1123. else
  1124. begin
  1125. if (delete_doubles) and
  1126. assigned(currNode) then
  1127. begin
  1128. NewNode.FLeft:=currNode.FLeft;
  1129. NewNode.FRight:=currNode.FRight;
  1130. if delete_doubles then
  1131. begin
  1132. currnode.FLeft:=nil;
  1133. currnode.FRight:=nil;
  1134. currnode.free;
  1135. end;
  1136. currNode:=NewNode;
  1137. insertNode:=NewNode;
  1138. end
  1139. else
  1140. insertNode:=currNode;
  1141. end;
  1142. end;
  1143. end;
  1144. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  1145. begin
  1146. if assigned(currtree) then
  1147. begin
  1148. inserttree(currtree.FLeft,currroot);
  1149. inserttree(currtree.FRight,currroot);
  1150. currtree.FRight:=nil;
  1151. currtree.FLeft:=nil;
  1152. insertNode(currtree,currroot);
  1153. end;
  1154. end;
  1155. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  1156. var
  1157. spdval : cardinal;
  1158. lasthp,
  1159. hp,hp2,hp3 : TNamedIndexItem;
  1160. {$ifdef compress}
  1161. oldsenc,newsenc:string;
  1162. {$else}
  1163. oldsenc:string absolute olds;
  1164. newsenc:string absolute news;
  1165. {$endif}
  1166. begin
  1167. {$ifdef compress}
  1168. oldsenc:=minilzw_encode(olds);
  1169. newsenc:=minilzw_encode(news);
  1170. {$endif}
  1171. spdval:=GetSpeedValue(olds);
  1172. if assigned(FHashArray) then
  1173. hp:=FHashArray^[spdval mod hasharraysize]
  1174. else
  1175. hp:=FRoot;
  1176. lasthp:=nil;
  1177. while assigned(hp) do
  1178. begin
  1179. if spdval>hp.SpeedValue then
  1180. begin
  1181. lasthp:=hp;
  1182. hp:=hp.FLeft
  1183. end
  1184. else
  1185. if spdval<hp.SpeedValue then
  1186. begin
  1187. lasthp:=hp;
  1188. hp:=hp.FRight
  1189. end
  1190. else
  1191. begin
  1192. if (hp.FName^=oldsenc) then
  1193. begin
  1194. { Get in hp2 the replacer for the root or hasharr }
  1195. hp2:=hp.FLeft;
  1196. hp3:=hp.FRight;
  1197. if not assigned(hp2) then
  1198. begin
  1199. hp2:=hp.FRight;
  1200. hp3:=hp.FLeft;
  1201. end;
  1202. { remove entry from the tree }
  1203. if assigned(lasthp) then
  1204. begin
  1205. if lasthp.FLeft=hp then
  1206. lasthp.FLeft:=hp2
  1207. else
  1208. lasthp.FRight:=hp2;
  1209. end
  1210. else
  1211. begin
  1212. if assigned(FHashArray) then
  1213. FHashArray^[spdval mod hasharraysize]:=hp2
  1214. else
  1215. FRoot:=hp2;
  1216. end;
  1217. { reinsert the hp3 in the tree from hp2 }
  1218. inserttree(hp3,hp2);
  1219. { reset Node with New values }
  1220. hp.FLeft:=nil;
  1221. hp.FRight:=nil;
  1222. stringdispose(hp.FName);
  1223. hp.FName:=stringdup(newsenc);
  1224. hp.FSpeedValue:=GetSpeedValue(news);
  1225. { reinsert }
  1226. if assigned(FHashArray) then
  1227. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  1228. else
  1229. rename:=insertNode(hp,FRoot);
  1230. exit;
  1231. end
  1232. else
  1233. if oldsenc>hp.FName^ then
  1234. begin
  1235. lasthp:=hp;
  1236. hp:=hp.FLeft
  1237. end
  1238. else
  1239. begin
  1240. lasthp:=hp;
  1241. hp:=hp.FRight;
  1242. end;
  1243. end;
  1244. end;
  1245. result := nil;
  1246. end;
  1247. function Tdictionary.search(const s:string):TNamedIndexItem;
  1248. var t:string;
  1249. begin
  1250. search:=speedsearch(s,getspeedvalue(s));
  1251. end;
  1252. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  1253. var
  1254. NewNode:TNamedIndexItem;
  1255. {$ifdef compress}
  1256. decn:string;
  1257. {$endif}
  1258. begin
  1259. if assigned(FHashArray) then
  1260. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  1261. else
  1262. NewNode:=FRoot;
  1263. while assigned(NewNode) do
  1264. begin
  1265. if SpeedValue>NewNode.SpeedValue then
  1266. NewNode:=NewNode.FLeft
  1267. else
  1268. if SpeedValue<NewNode.SpeedValue then
  1269. NewNode:=NewNode.FRight
  1270. else
  1271. begin
  1272. {$ifdef compress}
  1273. decn:=minilzw_decode(newnode.fname^);
  1274. if (decn=s) then
  1275. begin
  1276. speedsearch:=NewNode;
  1277. exit;
  1278. end
  1279. else
  1280. if s>decn then
  1281. NewNode:=NewNode.FLeft
  1282. else
  1283. NewNode:=NewNode.FRight;
  1284. {$else}
  1285. if (NewNode.FName^=s) then
  1286. begin
  1287. speedsearch:=NewNode;
  1288. exit;
  1289. end
  1290. else
  1291. if s>NewNode.FName^ then
  1292. NewNode:=NewNode.FLeft
  1293. else
  1294. NewNode:=NewNode.FRight;
  1295. {$endif}
  1296. end;
  1297. end;
  1298. speedsearch:=nil;
  1299. end;
  1300. {****************************************************************************
  1301. tsingleList
  1302. ****************************************************************************}
  1303. constructor tsingleList.create;
  1304. begin
  1305. First:=nil;
  1306. last:=nil;
  1307. end;
  1308. procedure tsingleList.reset;
  1309. begin
  1310. First:=nil;
  1311. last:=nil;
  1312. end;
  1313. procedure tsingleList.clear;
  1314. var
  1315. hp,hp2 : TNamedIndexItem;
  1316. begin
  1317. hp:=First;
  1318. while assigned(hp) do
  1319. begin
  1320. hp2:=hp;
  1321. hp:=hp.FListNext;
  1322. hp2.free;
  1323. end;
  1324. First:=nil;
  1325. last:=nil;
  1326. end;
  1327. procedure tsingleList.insert(p:TNamedIndexItem);
  1328. begin
  1329. if not assigned(First) then
  1330. First:=p
  1331. else
  1332. last.FListNext:=p;
  1333. last:=p;
  1334. p.FListNext:=nil;
  1335. end;
  1336. {****************************************************************************
  1337. tindexarray
  1338. ****************************************************************************}
  1339. constructor tindexarray.create(Agrowsize:integer);
  1340. begin
  1341. growsize:=Agrowsize;
  1342. size:=0;
  1343. count:=0;
  1344. data:=nil;
  1345. First:=nil;
  1346. noclear:=false;
  1347. end;
  1348. destructor tindexarray.destroy;
  1349. begin
  1350. if assigned(data) then
  1351. begin
  1352. if not noclear then
  1353. clear;
  1354. freemem(data);
  1355. data:=nil;
  1356. end;
  1357. end;
  1358. function tindexarray.search(nr:integer):TNamedIndexItem;
  1359. begin
  1360. if nr<=count then
  1361. search:=data^[nr]
  1362. else
  1363. search:=nil;
  1364. end;
  1365. procedure tindexarray.clear;
  1366. var
  1367. i : integer;
  1368. begin
  1369. for i:=1 to count do
  1370. if assigned(data^[i]) then
  1371. begin
  1372. data^[i].free;
  1373. data^[i]:=nil;
  1374. end;
  1375. count:=0;
  1376. First:=nil;
  1377. end;
  1378. procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
  1379. var
  1380. i : integer;
  1381. begin
  1382. for i:=1 to count do
  1383. if assigned(data^[i]) then
  1384. proc2call(data^[i],arg);
  1385. end;
  1386. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  1387. var
  1388. i : integer;
  1389. begin
  1390. for i:=1 to count do
  1391. if assigned(data^[i]) then
  1392. proc2call(data^[i],arg);
  1393. end;
  1394. procedure tindexarray.grow(gsize:integer);
  1395. var
  1396. osize : integer;
  1397. begin
  1398. osize:=size;
  1399. inc(size,gsize);
  1400. reallocmem(data,size*4);
  1401. fillchar(data^[osize+1],gsize*4,0);
  1402. end;
  1403. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  1404. var
  1405. i : integer;
  1406. begin
  1407. i:=p.Findexnr;
  1408. { update counter }
  1409. if i=count then
  1410. dec(count);
  1411. { update Linked List }
  1412. while (i>0) do
  1413. begin
  1414. dec(i);
  1415. if (i>0) and assigned(data^[i]) then
  1416. begin
  1417. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  1418. break;
  1419. end;
  1420. end;
  1421. if i=0 then
  1422. First:=p.FindexNext;
  1423. data^[p.FIndexnr]:=nil;
  1424. { clear entry }
  1425. p.FIndexnr:=-1;
  1426. p.FIndexNext:=nil;
  1427. end;
  1428. procedure tindexarray.delete(var p:TNamedIndexItem);
  1429. begin
  1430. deleteindex(p);
  1431. p.free;
  1432. p:=nil;
  1433. end;
  1434. procedure tindexarray.insert(p:TNamedIndexItem);
  1435. var
  1436. i : integer;
  1437. begin
  1438. if p.FIndexnr=-1 then
  1439. begin
  1440. inc(count);
  1441. p.FIndexnr:=count;
  1442. end;
  1443. if p.FIndexnr>count then
  1444. count:=p.FIndexnr;
  1445. if count>size then
  1446. grow(((count div growsize)+1)*growsize);
  1447. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  1448. data^[p.FIndexnr]:=p;
  1449. { update Linked List backward }
  1450. i:=p.FIndexnr;
  1451. while (i>0) do
  1452. begin
  1453. dec(i);
  1454. if (i>0) and assigned(data^[i]) then
  1455. begin
  1456. data^[i].FIndexNext:=p;
  1457. break;
  1458. end;
  1459. end;
  1460. if i=0 then
  1461. First:=p;
  1462. { update Linked List forward }
  1463. i:=p.FIndexnr;
  1464. while (i<=count) do
  1465. begin
  1466. inc(i);
  1467. if (i<=count) and assigned(data^[i]) then
  1468. begin
  1469. p.FIndexNext:=data^[i];
  1470. exit;
  1471. end;
  1472. end;
  1473. if i>count then
  1474. p.FIndexNext:=nil;
  1475. end;
  1476. procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
  1477. var
  1478. i : integer;
  1479. begin
  1480. newp.FIndexnr:=oldp.FIndexnr;
  1481. newp.FIndexNext:=oldp.FIndexNext;
  1482. data^[newp.FIndexnr]:=newp;
  1483. if First=oldp then
  1484. First:=newp;
  1485. { update Linked List backward }
  1486. i:=newp.FIndexnr;
  1487. while (i>0) do
  1488. begin
  1489. dec(i);
  1490. if (i>0) and assigned(data^[i]) then
  1491. begin
  1492. data^[i].FIndexNext:=newp;
  1493. break;
  1494. end;
  1495. end;
  1496. end;
  1497. {****************************************************************************
  1498. tdynamicarray
  1499. ****************************************************************************}
  1500. constructor tdynamicarray.create(Ablocksize:integer);
  1501. begin
  1502. FPosn:=0;
  1503. FPosnblock:=nil;
  1504. FFirstblock:=nil;
  1505. FLastblock:=nil;
  1506. Fblocksize:=Ablocksize;
  1507. grow;
  1508. end;
  1509. destructor tdynamicarray.destroy;
  1510. var
  1511. hp : pdynamicblock;
  1512. begin
  1513. while assigned(FFirstblock) do
  1514. begin
  1515. hp:=FFirstblock;
  1516. FFirstblock:=FFirstblock^.Next;
  1517. Freemem(hp);
  1518. end;
  1519. end;
  1520. function tdynamicarray.size:integer;
  1521. begin
  1522. if assigned(FLastblock) then
  1523. size:=FLastblock^.pos+FLastblock^.used
  1524. else
  1525. size:=0;
  1526. end;
  1527. procedure tdynamicarray.reset;
  1528. var
  1529. hp : pdynamicblock;
  1530. begin
  1531. while assigned(FFirstblock) do
  1532. begin
  1533. hp:=FFirstblock;
  1534. FFirstblock:=FFirstblock^.Next;
  1535. Freemem(hp);
  1536. end;
  1537. FPosn:=0;
  1538. FPosnblock:=nil;
  1539. FFirstblock:=nil;
  1540. FLastblock:=nil;
  1541. grow;
  1542. end;
  1543. procedure tdynamicarray.grow;
  1544. var
  1545. nblock : pdynamicblock;
  1546. begin
  1547. Getmem(nblock,blocksize+dynamicblockbasesize);
  1548. if not assigned(FFirstblock) then
  1549. begin
  1550. FFirstblock:=nblock;
  1551. FPosnblock:=nblock;
  1552. nblock^.pos:=0;
  1553. end
  1554. else
  1555. begin
  1556. FLastblock^.Next:=nblock;
  1557. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1558. end;
  1559. nblock^.used:=0;
  1560. nblock^.Next:=nil;
  1561. fillchar(nblock^.data,blocksize,0);
  1562. FLastblock:=nblock;
  1563. end;
  1564. procedure tdynamicarray.align(i:integer);
  1565. var
  1566. j : integer;
  1567. begin
  1568. j:=(FPosn mod i);
  1569. if j<>0 then
  1570. begin
  1571. j:=i-j;
  1572. if FPosnblock^.used+j>blocksize then
  1573. begin
  1574. dec(j,blocksize-FPosnblock^.used);
  1575. FPosnblock^.used:=blocksize;
  1576. grow;
  1577. FPosnblock:=FLastblock;
  1578. end;
  1579. inc(FPosnblock^.used,j);
  1580. inc(FPosn,j);
  1581. end;
  1582. end;
  1583. procedure tdynamicarray.seek(i:integer);
  1584. begin
  1585. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  1586. begin
  1587. { set FPosnblock correct if the size is bigger then
  1588. the current block }
  1589. if FPosnblock^.pos>i then
  1590. FPosnblock:=FFirstblock;
  1591. while assigned(FPosnblock) do
  1592. begin
  1593. if FPosnblock^.pos+blocksize>i then
  1594. break;
  1595. FPosnblock:=FPosnblock^.Next;
  1596. end;
  1597. { not found ? then increase blocks }
  1598. if not assigned(FPosnblock) then
  1599. begin
  1600. repeat
  1601. { the current FLastblock is now also fully used }
  1602. FLastblock^.used:=blocksize;
  1603. grow;
  1604. FPosnblock:=FLastblock;
  1605. until FPosnblock^.pos+blocksize>=i;
  1606. end;
  1607. end;
  1608. FPosn:=i;
  1609. if FPosn mod blocksize>FPosnblock^.used then
  1610. FPosnblock^.used:=FPosn mod blocksize;
  1611. end;
  1612. procedure tdynamicarray.write(const d;len:integer);
  1613. var
  1614. p : pchar;
  1615. i,j : integer;
  1616. begin
  1617. p:=pchar(@d);
  1618. while (len>0) do
  1619. begin
  1620. i:=FPosn mod blocksize;
  1621. if i+len>=blocksize then
  1622. begin
  1623. j:=blocksize-i;
  1624. move(p^,FPosnblock^.data[i],j);
  1625. inc(p,j);
  1626. inc(FPosn,j);
  1627. dec(len,j);
  1628. FPosnblock^.used:=blocksize;
  1629. if assigned(FPosnblock^.Next) then
  1630. FPosnblock:=FPosnblock^.Next
  1631. else
  1632. begin
  1633. grow;
  1634. FPosnblock:=FLastblock;
  1635. end;
  1636. end
  1637. else
  1638. begin
  1639. move(p^,FPosnblock^.data[i],len);
  1640. inc(p,len);
  1641. inc(FPosn,len);
  1642. i:=FPosn mod blocksize;
  1643. if i>FPosnblock^.used then
  1644. FPosnblock^.used:=i;
  1645. len:=0;
  1646. end;
  1647. end;
  1648. end;
  1649. procedure tdynamicarray.writestr(const s:string);
  1650. begin
  1651. write(s[1],length(s));
  1652. end;
  1653. function tdynamicarray.read(var d;len:integer):integer;
  1654. var
  1655. p : pchar;
  1656. i,j,res : integer;
  1657. begin
  1658. res:=0;
  1659. p:=pchar(@d);
  1660. while (len>0) do
  1661. begin
  1662. i:=FPosn mod blocksize;
  1663. if i+len>=FPosnblock^.used then
  1664. begin
  1665. j:=FPosnblock^.used-i;
  1666. move(FPosnblock^.data[i],p^,j);
  1667. inc(p,j);
  1668. inc(FPosn,j);
  1669. inc(res,j);
  1670. dec(len,j);
  1671. if assigned(FPosnblock^.Next) then
  1672. FPosnblock:=FPosnblock^.Next
  1673. else
  1674. break;
  1675. end
  1676. else
  1677. begin
  1678. move(FPosnblock^.data[i],p^,len);
  1679. inc(p,len);
  1680. inc(FPosn,len);
  1681. inc(res,len);
  1682. len:=0;
  1683. end;
  1684. end;
  1685. read:=res;
  1686. end;
  1687. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  1688. var
  1689. i,left : integer;
  1690. begin
  1691. if maxlen=-1 then
  1692. maxlen:=maxlongint;
  1693. repeat
  1694. left:=blocksize-FPosnblock^.used;
  1695. if left>maxlen then
  1696. left:=maxlen;
  1697. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  1698. dec(maxlen,i);
  1699. inc(FPosnblock^.used,i);
  1700. if FPosnblock^.used=blocksize then
  1701. begin
  1702. if assigned(FPosnblock^.Next) then
  1703. FPosnblock:=FPosnblock^.Next
  1704. else
  1705. begin
  1706. grow;
  1707. FPosnblock:=FLastblock;
  1708. end;
  1709. end;
  1710. until (i<left) or (maxlen=0);
  1711. end;
  1712. procedure tdynamicarray.writestream(f:TCStream);
  1713. var
  1714. hp : pdynamicblock;
  1715. begin
  1716. hp:=FFirstblock;
  1717. while assigned(hp) do
  1718. begin
  1719. f.Write(hp^.data,hp^.used);
  1720. hp:=hp^.Next;
  1721. end;
  1722. end;
  1723. end.
  1724. {
  1725. $Log$
  1726. Revision 1.30 2004-01-15 15:16:17 daniel
  1727. * Some minor stuff
  1728. * Managed to eliminate speed effects of string compression
  1729. Revision 1.29 2004/01/11 23:56:19 daniel
  1730. * Experiment: Compress strings to save memory
  1731. Did not save a single byte of mem; clearly the core size is boosted by
  1732. temporary memory usage...
  1733. Revision 1.28 2003/10/23 14:44:07 peter
  1734. * splitted buildderef and buildderefimpl to fix interface crc
  1735. calculation
  1736. Revision 1.27 2003/10/22 20:40:00 peter
  1737. * write derefdata in a separate ppu entry
  1738. Revision 1.26 2003/10/11 16:06:42 florian
  1739. * fixed some MMX<->SSE
  1740. * started to fix ppc, needs an overhaul
  1741. + stabs info improve for spilling, not sure if it works correctly/completly
  1742. - MMX_SUPPORT removed from Makefile.fpc
  1743. Revision 1.25 2003/09/29 20:52:50 peter
  1744. * insertbefore added
  1745. Revision 1.24 2003/09/24 13:02:10 marco
  1746. * (Peter) patch to fix snapshot
  1747. Revision 1.23 2003/06/09 12:19:34 peter
  1748. * insertlistafter added
  1749. Revision 1.22 2002/12/15 19:34:31 florian
  1750. + some front end stuff for vs_hidden added
  1751. Revision 1.21 2002/11/24 18:18:39 carl
  1752. - remove some unused defines
  1753. Revision 1.20 2002/10/05 12:43:23 carl
  1754. * fixes for Delphi 6 compilation
  1755. (warning : Some features do not work under Delphi)
  1756. Revision 1.19 2002/09/09 17:34:14 peter
  1757. * tdicationary.replace added to replace and item in a dictionary. This
  1758. is only allowed for the same name
  1759. * varsyms are inserted in symtable before the types are parsed. This
  1760. fixes the long standing "var longint : longint" bug
  1761. - consume_idlist and idstringlist removed. The loops are inserted
  1762. at the callers place and uses the symtable for duplicate id checking
  1763. Revision 1.18 2002/09/05 19:29:42 peter
  1764. * memdebug enhancements
  1765. Revision 1.17 2002/08/11 13:24:11 peter
  1766. * saving of asmsymbols in ppu supported
  1767. * asmsymbollist global is removed and moved into a new class
  1768. tasmlibrarydata that will hold the info of a .a file which
  1769. corresponds with a single module. Added librarydata to tmodule
  1770. to keep the library info stored for the module. In the future the
  1771. objectfiles will also be stored to the tasmlibrarydata class
  1772. * all getlabel/newasmsymbol and friends are moved to the new class
  1773. Revision 1.16 2002/08/09 19:08:53 carl
  1774. + fix incorrect comment in insertlistcopy
  1775. Revision 1.15 2002/07/01 18:46:21 peter
  1776. * internal linker
  1777. * reorganized aasm layer
  1778. Revision 1.14 2002/06/17 13:56:14 jonas
  1779. * tdictionary.rename() returns nil if the original object wasn't found
  1780. (reported by Sergey Korshunoff <[email protected]>)
  1781. Revision 1.13 2002/05/18 13:34:05 peter
  1782. * readded missing revisions
  1783. Revision 1.12 2002/05/16 19:46:35 carl
  1784. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1785. + try to fix temp allocation (still in ifdef)
  1786. + generic constructor calls
  1787. + start of tassembler / tmodulebase class cleanup
  1788. Revision 1.10 2002/05/12 16:53:04 peter
  1789. * moved entry and exitcode to ncgutil and cgobj
  1790. * foreach gets extra argument for passing local data to the
  1791. iterator function
  1792. * -CR checks also class typecasts at runtime by changing them
  1793. into as
  1794. * fixed compiler to cycle with the -CR option
  1795. * fixed stabs with elf writer, finally the global variables can
  1796. be watched
  1797. * removed a lot of routines from cga unit and replaced them by
  1798. calls to cgobj
  1799. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1800. u32bit then the other is typecasted also to u32bit without giving
  1801. a rangecheck warning/error.
  1802. * fixed pascal calling method with reversing also the high tree in
  1803. the parast, detected by tcalcst3 test
  1804. }