cobjects.pas 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This module provides some basic objects
  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 cobjects;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cutils;
  23. const
  24. { the real size will be [-hasharray..hasharray] ! }
  25. hasharraysize = 2047;
  26. type
  27. pfileposinfo = ^tfileposinfo;
  28. tfileposinfo = record
  29. line : longint;
  30. column : word;
  31. fileindex : word;
  32. end;
  33. pmemdebug = ^tmemdebug;
  34. tmemdebug = object
  35. constructor init(const s:string);
  36. destructor done;
  37. procedure show;
  38. private
  39. startmem : longint;
  40. infostr : string[40];
  41. end;
  42. plinkedlist_item = ^tlinkedlist_item;
  43. tlinkedlist_item = object
  44. next,previous : plinkedlist_item;
  45. { does nothing }
  46. constructor init;
  47. destructor done;virtual;
  48. function getcopy:plinkedlist_item;virtual;
  49. end;
  50. pstring_item = ^tstring_item;
  51. tstring_item = object(tlinkedlist_item)
  52. str : pstring;
  53. constructor init(const s : string);
  54. destructor done;virtual;
  55. end;
  56. { this implements a double linked list }
  57. plinkedlist = ^tlinkedlist;
  58. tlinkedlist = object
  59. first,last : plinkedlist_item;
  60. constructor init;
  61. destructor done;
  62. { disposes the items of the list }
  63. procedure clear;
  64. { concats a new item at the end }
  65. procedure concat(p : plinkedlist_item);
  66. { inserts a new item at the begin }
  67. procedure insert(p : plinkedlist_item);
  68. { inserts another list at the begin and make this list empty }
  69. procedure insertlist(p : plinkedlist);
  70. { concats another list at the end and make this list empty }
  71. procedure concatlist(p : plinkedlist);
  72. procedure concatlistcopy(p : plinkedlist);
  73. { removes p from the list (p isn't disposed) }
  74. { it's not tested if p is in the list ! }
  75. procedure remove(p : plinkedlist_item);
  76. { is the linkedlist empty ? }
  77. function empty:boolean;
  78. { items in the list }
  79. function count:longint;
  80. end;
  81. { some help data types }
  82. pstringqueueitem = ^tstringqueueitem;
  83. tstringqueueitem = object
  84. data : pstring;
  85. next : pstringqueueitem;
  86. end;
  87. { String Queue}
  88. PStringQueue=^TStringQueue;
  89. TStringQueue=object
  90. first,last : PStringqueueItem;
  91. constructor Init;
  92. destructor Done;
  93. function Empty:boolean;
  94. function Get:string;
  95. function Find(const s:string):PStringqueueItem;
  96. function Delete(const s:string):boolean;
  97. procedure Insert(const s:string);
  98. procedure Concat(const s:string);
  99. procedure Clear;
  100. end;
  101. { containeritem }
  102. pcontaineritem = ^tcontaineritem;
  103. tcontaineritem = object
  104. next : pcontaineritem;
  105. constructor init;
  106. destructor done;virtual;
  107. end;
  108. { container }
  109. pcontainer = ^tcontainer;
  110. tcontainer = object
  111. root,
  112. last : pcontaineritem;
  113. constructor init;
  114. destructor done;
  115. { true when the container is empty }
  116. function empty:boolean;
  117. { amount of strings in the container }
  118. function count:longint;
  119. { inserts a string }
  120. procedure insert(item:pcontaineritem);
  121. { gets a string }
  122. function get:pcontaineritem;
  123. { deletes all items }
  124. procedure clear;
  125. end;
  126. { containeritem }
  127. pstringcontaineritem = ^tstringcontaineritem;
  128. tstringcontaineritem = object(tcontaineritem)
  129. data : pstring;
  130. file_info : tfileposinfo;
  131. constructor init(const s:string);
  132. constructor Init_TokenInfo(const s:string;const pos:tfileposinfo);
  133. destructor done;virtual;
  134. end;
  135. { string container }
  136. pstringcontainer = ^tstringcontainer;
  137. tstringcontainer = object(tcontainer)
  138. doubles : boolean; { if this is set to true, doubles are allowed }
  139. constructor init;
  140. constructor init_no_double;
  141. procedure insert(const s : string);
  142. procedure insert_with_tokeninfo(const s : string;const file_info : tfileposinfo);
  143. { gets a string }
  144. function get : string;
  145. function get_with_tokeninfo(var file_info : tfileposinfo) : string;
  146. { true if string is in the container }
  147. function find(const s:string):boolean;
  148. end;
  149. { namedindexobect for use with dictionary and indexarray }
  150. Pnamedindexobject=^Tnamedindexobject;
  151. Tnamedindexobject=object
  152. { indexarray }
  153. indexnr : longint;
  154. indexnext : Pnamedindexobject;
  155. { dictionary }
  156. _name : Pstring;
  157. _valuename : Pstring; { uppercase name }
  158. left,right : Pnamedindexobject;
  159. speedvalue : longint;
  160. { singlelist }
  161. listnext : Pnamedindexobject;
  162. constructor init;
  163. constructor initname(const n:string);
  164. destructor done;virtual;
  165. procedure setname(const n:string);virtual;
  166. function name:string;virtual;
  167. end;
  168. Pdictionaryhasharray=^Tdictionaryhasharray;
  169. Tdictionaryhasharray=array[-hasharraysize..hasharraysize] of Pnamedindexobject;
  170. Tnamedindexcallback = procedure(p:Pnamedindexobject);
  171. Pdictionary=^Tdictionary;
  172. Tdictionary=object
  173. noclear : boolean;
  174. replace_existing : boolean;
  175. constructor init;
  176. destructor done;virtual;
  177. procedure usehash;
  178. procedure clear;
  179. function delete(const s:string):Pnamedindexobject;
  180. function empty:boolean;
  181. procedure foreach(proc2call:Tnamedindexcallback);
  182. function insert(obj:Pnamedindexobject):Pnamedindexobject;
  183. function rename(const olds,news : string):Pnamedindexobject;
  184. function search(const s:string):Pnamedindexobject;
  185. function speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  186. private
  187. root : Pnamedindexobject;
  188. hasharray : Pdictionaryhasharray;
  189. procedure cleartree(obj:Pnamedindexobject);
  190. function insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  191. procedure inserttree(currtree,currroot:Pnamedindexobject);
  192. end;
  193. psinglelist=^tsinglelist;
  194. tsinglelist=object
  195. first,
  196. last : Pnamedindexobject;
  197. constructor init;
  198. destructor done;
  199. procedure reset;
  200. procedure clear;
  201. procedure insert(p:Pnamedindexobject);
  202. end;
  203. const
  204. dynamicblockbasesize = 12;
  205. type
  206. pdynamicblock = ^tdynamicblock;
  207. tdynamicblock = record
  208. pos,
  209. used : longint;
  210. next : pdynamicblock;
  211. data : array[0..high(longint)-20] of byte;
  212. end;
  213. pdynamicarray = ^tdynamicarray;
  214. tdynamicarray = object
  215. blocksize : longint;
  216. firstblock,
  217. lastblock : pdynamicblock;
  218. constructor init(Ablocksize:longint);
  219. destructor done;
  220. function size:longint;
  221. procedure align(i:longint);
  222. procedure seek(i:longint);
  223. procedure write(const d;len:longint);
  224. procedure writestr(const s:string);
  225. function read(var d;len:longint):longint;
  226. procedure blockwrite(var f:file);
  227. private
  228. posn : longint;
  229. posnblock : pdynamicblock;
  230. procedure grow;
  231. end;
  232. tindexobjectarray=array[1..16000] of Pnamedindexobject;
  233. Pnamedindexobjectarray=^tindexobjectarray;
  234. pindexarray=^tindexarray;
  235. tindexarray=object
  236. noclear : boolean;
  237. first : Pnamedindexobject;
  238. count : longint;
  239. constructor init(Agrowsize:longint);
  240. destructor done;
  241. procedure clear;
  242. procedure foreach(proc2call : Tnamedindexcallback);
  243. procedure deleteindex(p:Pnamedindexobject);
  244. procedure delete(var p:Pnamedindexobject);
  245. procedure insert(p:Pnamedindexobject);
  246. function search(nr:longint):Pnamedindexobject;
  247. private
  248. growsize,
  249. size : longint;
  250. data : Pnamedindexobjectarray;
  251. procedure grow(gsize:longint);
  252. end;
  253. {$ifdef fixLeaksOnError}
  254. PStackItem = ^TStackItem;
  255. TStackItem = record
  256. next: PStackItem;
  257. data: pointer;
  258. end;
  259. PStack = ^TStack;
  260. TStack = object
  261. constructor init;
  262. destructor done;
  263. procedure push(p: pointer);
  264. function pop: pointer;
  265. function top: pointer;
  266. function isEmpty: boolean;
  267. private
  268. head: PStackItem;
  269. end;
  270. {$endif fixLeaksOnError}
  271. implementation
  272. {*****************************************************************************
  273. Memory debug
  274. *****************************************************************************}
  275. constructor tmemdebug.init(const s:string);
  276. begin
  277. infostr:=s;
  278. {$ifdef Delphi}
  279. startmem:=0;
  280. {$else}
  281. startmem:=memavail;
  282. {$endif Delphi}
  283. end;
  284. procedure tmemdebug.show;
  285. {$ifndef Delphi}
  286. var
  287. l : longint;
  288. {$endif}
  289. begin
  290. {$ifndef Delphi}
  291. write('memory [',infostr,'] ');
  292. l:=memavail;
  293. if l>startmem then
  294. writeln(l-startmem,' released')
  295. else
  296. writeln(startmem-l,' allocated');
  297. {$endif Delphi}
  298. end;
  299. destructor tmemdebug.done;
  300. begin
  301. show;
  302. end;
  303. {*****************************************************************************
  304. Stack
  305. *****************************************************************************}
  306. {$ifdef fixLeaksOnError}
  307. constructor TStack.init;
  308. begin
  309. head := nil;
  310. end;
  311. procedure TStack.push(p: pointer);
  312. var s: PStackItem;
  313. begin
  314. new(s);
  315. s^.data := p;
  316. s^.next := head;
  317. head := s;
  318. end;
  319. function TStack.pop: pointer;
  320. var s: PStackItem;
  321. begin
  322. pop := top;
  323. if assigned(head) then
  324. begin
  325. s := head^.next;
  326. dispose(head);
  327. head := s;
  328. end
  329. end;
  330. function TStack.top: pointer;
  331. begin
  332. if not isEmpty then
  333. top := head^.data
  334. else top := NIL;
  335. end;
  336. function TStack.isEmpty: boolean;
  337. begin
  338. isEmpty := head = nil;
  339. end;
  340. destructor TStack.done;
  341. var temp: PStackItem;
  342. begin
  343. while head <> nil do
  344. begin
  345. temp := head^.next;
  346. dispose(head);
  347. head := temp;
  348. end;
  349. end;
  350. {$endif fixLeaksOnError}
  351. {****************************************************************************
  352. TStringQueue
  353. ****************************************************************************}
  354. constructor TStringQueue.Init;
  355. begin
  356. first:=nil;
  357. last:=nil;
  358. end;
  359. function TStringQueue.Empty:boolean;
  360. begin
  361. Empty:=(first=nil);
  362. end;
  363. function TStringQueue.Get:string;
  364. var
  365. newnode : pstringqueueitem;
  366. begin
  367. if first=nil then
  368. begin
  369. Get:='';
  370. exit;
  371. end;
  372. Get:=first^.data^;
  373. stringdispose(first^.data);
  374. newnode:=first;
  375. first:=first^.next;
  376. dispose(newnode);
  377. end;
  378. function TStringQueue.Find(const s:string):PStringqueueItem;
  379. var
  380. p : PStringqueueItem;
  381. begin
  382. p:=first;
  383. while assigned(p) do
  384. begin
  385. if p^.data^=s then
  386. break;
  387. p:=p^.next;
  388. end;
  389. Find:=p;
  390. end;
  391. function TStringQueue.Delete(const s:string):boolean;
  392. var
  393. prev,p : PStringqueueItem;
  394. begin
  395. Delete:=false;
  396. prev:=nil;
  397. p:=first;
  398. while assigned(p) do
  399. begin
  400. if p^.data^=s then
  401. begin
  402. if p=last then
  403. last:=prev;
  404. if assigned(prev) then
  405. prev^.next:=p^.next
  406. else
  407. first:=p^.next;
  408. dispose(p);
  409. Delete:=true;
  410. exit;
  411. end;
  412. prev:=p;
  413. p:=p^.next;
  414. end;
  415. end;
  416. procedure TStringQueue.Insert(const s:string);
  417. var
  418. newnode : pstringqueueitem;
  419. begin
  420. new(newnode);
  421. newnode^.next:=first;
  422. newnode^.data:=stringdup(s);
  423. first:=newnode;
  424. if last=nil then
  425. last:=newnode;
  426. end;
  427. procedure TStringQueue.Concat(const s:string);
  428. var
  429. newnode : pstringqueueitem;
  430. begin
  431. new(newnode);
  432. newnode^.next:=nil;
  433. newnode^.data:=stringdup(s);
  434. if first=nil then
  435. first:=newnode
  436. else
  437. last^.next:=newnode;
  438. last:=newnode;
  439. end;
  440. procedure TStringQueue.Clear;
  441. var
  442. newnode : pstringqueueitem;
  443. begin
  444. while (first<>nil) do
  445. begin
  446. newnode:=first;
  447. stringdispose(first^.data);
  448. first:=first^.next;
  449. dispose(newnode);
  450. end;
  451. last:=nil;
  452. end;
  453. destructor TStringQueue.Done;
  454. begin
  455. Clear;
  456. end;
  457. {****************************************************************************
  458. TContainerItem
  459. ****************************************************************************}
  460. constructor TContainerItem.Init;
  461. begin
  462. end;
  463. destructor TContainerItem.Done;
  464. begin
  465. end;
  466. {****************************************************************************
  467. TStringContainerItem
  468. ****************************************************************************}
  469. constructor TStringContainerItem.Init(const s:string);
  470. begin
  471. inherited Init;
  472. data:=stringdup(s);
  473. file_info.fileindex:=0;
  474. file_info.line:=0;
  475. file_info.column:=0;
  476. end;
  477. constructor TStringContainerItem.Init_TokenInfo(const s:string;const pos:tfileposinfo);
  478. begin
  479. inherited Init;
  480. data:=stringdup(s);
  481. file_info:=pos;
  482. end;
  483. destructor TStringContainerItem.Done;
  484. begin
  485. stringdispose(data);
  486. end;
  487. {****************************************************************************
  488. TCONTAINER
  489. ****************************************************************************}
  490. constructor tcontainer.init;
  491. begin
  492. root:=nil;
  493. last:=nil;
  494. end;
  495. destructor tcontainer.done;
  496. begin
  497. clear;
  498. end;
  499. function tcontainer.empty:boolean;
  500. begin
  501. empty:=(root=nil);
  502. end;
  503. function tcontainer.count:longint;
  504. var
  505. i : longint;
  506. p : pcontaineritem;
  507. begin
  508. i:=0;
  509. p:=root;
  510. while assigned(p) do
  511. begin
  512. p:=p^.next;
  513. inc(i);
  514. end;
  515. count:=i;
  516. end;
  517. procedure tcontainer.insert(item:pcontaineritem);
  518. begin
  519. item^.next:=nil;
  520. if root=nil then
  521. root:=item
  522. else
  523. last^.next:=item;
  524. last:=item;
  525. end;
  526. procedure tcontainer.clear;
  527. var
  528. newnode : pcontaineritem;
  529. begin
  530. newnode:=root;
  531. while assigned(newnode) do
  532. begin
  533. root:=newnode^.next;
  534. dispose(newnode,done);
  535. newnode:=root;
  536. end;
  537. last:=nil;
  538. root:=nil;
  539. end;
  540. function tcontainer.get:pcontaineritem;
  541. begin
  542. if root=nil then
  543. get:=nil
  544. else
  545. begin
  546. get:=root;
  547. root:=root^.next;
  548. end;
  549. end;
  550. {****************************************************************************
  551. TSTRINGCONTAINER
  552. ****************************************************************************}
  553. constructor tstringcontainer.init;
  554. begin
  555. inherited init;
  556. doubles:=true;
  557. end;
  558. constructor tstringcontainer.init_no_double;
  559. begin
  560. inherited init;
  561. doubles:=false;
  562. end;
  563. procedure tstringcontainer.insert(const s : string);
  564. var
  565. newnode : pstringcontaineritem;
  566. begin
  567. if (s='') or
  568. ((not doubles) and find(s)) then
  569. exit;
  570. new(newnode,init(s));
  571. inherited insert(newnode);
  572. end;
  573. procedure tstringcontainer.insert_with_tokeninfo(const s : string; const file_info : tfileposinfo);
  574. var
  575. newnode : pstringcontaineritem;
  576. begin
  577. if (not doubles) and find(s) then
  578. exit;
  579. new(newnode,init_tokeninfo(s,file_info));
  580. inherited insert(newnode);
  581. end;
  582. function tstringcontainer.get : string;
  583. var
  584. p : pstringcontaineritem;
  585. begin
  586. p:=pstringcontaineritem(inherited get);
  587. if p=nil then
  588. get:=''
  589. else
  590. begin
  591. get:=p^.data^;
  592. dispose(p,done);
  593. end;
  594. end;
  595. function tstringcontainer.get_with_tokeninfo(var file_info : tfileposinfo) : string;
  596. var
  597. p : pstringcontaineritem;
  598. begin
  599. p:=pstringcontaineritem(inherited get);
  600. if p=nil then
  601. begin
  602. get_with_tokeninfo:='';
  603. file_info.fileindex:=0;
  604. file_info.line:=0;
  605. file_info.column:=0;
  606. end
  607. else
  608. begin
  609. get_with_tokeninfo:=p^.data^;
  610. file_info:=p^.file_info;
  611. dispose(p,done);
  612. end;
  613. end;
  614. function tstringcontainer.find(const s:string):boolean;
  615. var
  616. newnode : pstringcontaineritem;
  617. begin
  618. find:=false;
  619. newnode:=pstringcontaineritem(root);
  620. while assigned(newnode) do
  621. begin
  622. if newnode^.data^=s then
  623. begin
  624. find:=true;
  625. exit;
  626. end;
  627. newnode:=pstringcontaineritem(newnode^.next);
  628. end;
  629. end;
  630. {****************************************************************************
  631. TLINKEDLIST_ITEM
  632. ****************************************************************************}
  633. constructor tlinkedlist_item.init;
  634. begin
  635. previous:=nil;
  636. next:=nil;
  637. end;
  638. destructor tlinkedlist_item.done;
  639. begin
  640. end;
  641. function tlinkedlist_item.getcopy:plinkedlist_item;
  642. var
  643. l : longint;
  644. p : plinkedlist_item;
  645. begin
  646. l:=sizeof(self);
  647. getmem(p,l);
  648. move(self,p^,l);
  649. getcopy:=p;
  650. end;
  651. {****************************************************************************
  652. TSTRING_ITEM
  653. ****************************************************************************}
  654. constructor tstring_item.init(const s : string);
  655. begin
  656. str:=stringdup(s);
  657. end;
  658. destructor tstring_item.done;
  659. begin
  660. stringdispose(str);
  661. inherited done;
  662. end;
  663. {****************************************************************************
  664. TLINKEDLIST
  665. ****************************************************************************}
  666. constructor tlinkedlist.init;
  667. begin
  668. first:=nil;
  669. last:=nil;
  670. end;
  671. destructor tlinkedlist.done;
  672. begin
  673. clear;
  674. end;
  675. procedure tlinkedlist.clear;
  676. var
  677. newnode : plinkedlist_item;
  678. begin
  679. newnode:=first;
  680. while assigned(newnode) do
  681. begin
  682. first:=newnode^.next;
  683. dispose(newnode,done);
  684. newnode:=first;
  685. end;
  686. end;
  687. procedure tlinkedlist.insertlist(p : plinkedlist);
  688. begin
  689. { empty list ? }
  690. if not(assigned(p^.first)) then
  691. exit;
  692. p^.last^.next:=first;
  693. { we have a double linked list }
  694. if assigned(first) then
  695. first^.previous:=p^.last;
  696. first:=p^.first;
  697. if not(assigned(last)) then
  698. last:=p^.last;
  699. { p becomes empty }
  700. p^.first:=nil;
  701. p^.last:=nil;
  702. end;
  703. procedure tlinkedlist.concat(p : plinkedlist_item);
  704. begin
  705. if not(assigned(first)) then
  706. begin
  707. first:=p;
  708. p^.previous:=nil;
  709. p^.next:=nil;
  710. end
  711. else
  712. begin
  713. last^.next:=p;
  714. p^.previous:=last;
  715. p^.next:=nil;
  716. end;
  717. last:=p;
  718. end;
  719. procedure tlinkedlist.insert(p : plinkedlist_item);
  720. begin
  721. if not(assigned(first)) then
  722. begin
  723. last:=p;
  724. p^.previous:=nil;
  725. p^.next:=nil;
  726. end
  727. else
  728. begin
  729. first^.previous:=p;
  730. p^.previous:=nil;
  731. p^.next:=first;
  732. end;
  733. first:=p;
  734. end;
  735. procedure tlinkedlist.remove(p : plinkedlist_item);
  736. begin
  737. if not(assigned(p)) then
  738. exit;
  739. if (first=p) and (last=p) then
  740. begin
  741. first:=nil;
  742. last:=nil;
  743. end
  744. else if first=p then
  745. begin
  746. first:=p^.next;
  747. if assigned(first) then
  748. first^.previous:=nil;
  749. end
  750. else if last=p then
  751. begin
  752. last:=last^.previous;
  753. if assigned(last) then
  754. last^.next:=nil;
  755. end
  756. else
  757. begin
  758. p^.previous^.next:=p^.next;
  759. p^.next^.previous:=p^.previous;
  760. end;
  761. p^.next:=nil;
  762. p^.previous:=nil;
  763. end;
  764. procedure tlinkedlist.concatlist(p : plinkedlist);
  765. begin
  766. if not(assigned(p^.first)) then
  767. exit;
  768. if not(assigned(first)) then
  769. first:=p^.first
  770. else
  771. begin
  772. last^.next:=p^.first;
  773. p^.first^.previous:=last;
  774. end;
  775. last:=p^.last;
  776. { make p empty }
  777. p^.last:=nil;
  778. p^.first:=nil;
  779. end;
  780. procedure tlinkedlist.concatlistcopy(p : plinkedlist);
  781. var
  782. newnode,newnode2 : plinkedlist_item;
  783. begin
  784. newnode:=p^.first;
  785. while assigned(newnode) do
  786. begin
  787. newnode2:=newnode^.getcopy;
  788. if assigned(newnode2) then
  789. begin
  790. if not(assigned(first)) then
  791. begin
  792. first:=newnode2;
  793. newnode2^.previous:=nil;
  794. newnode2^.next:=nil;
  795. end
  796. else
  797. begin
  798. last^.next:=newnode2;
  799. newnode2^.previous:=last;
  800. newnode2^.next:=nil;
  801. end;
  802. last:=newnode2;
  803. end;
  804. newnode:=newnode^.next;
  805. end;
  806. end;
  807. function tlinkedlist.empty:boolean;
  808. begin
  809. empty:=(first=nil);
  810. end;
  811. function tlinkedlist.count:longint;
  812. var
  813. i : longint;
  814. hp : plinkedlist_item;
  815. begin
  816. hp:=first;
  817. i:=0;
  818. while assigned(hp) do
  819. begin
  820. inc(i);
  821. hp:=hp^.next;
  822. end;
  823. count:=i;
  824. end;
  825. {****************************************************************************
  826. Tnamedindexobject
  827. ****************************************************************************}
  828. constructor Tnamedindexobject.init;
  829. begin
  830. { index }
  831. indexnr:=-1;
  832. indexnext:=nil;
  833. { dictionary }
  834. left:=nil;
  835. right:=nil;
  836. _name:=nil;
  837. speedvalue:=-1;
  838. { list }
  839. listnext:=nil;
  840. end;
  841. constructor Tnamedindexobject.initname(const n:string);
  842. begin
  843. { index }
  844. indexnr:=-1;
  845. indexnext:=nil;
  846. { dictionary }
  847. left:=nil;
  848. right:=nil;
  849. speedvalue:=-1;
  850. _name:=stringdup(n);
  851. { list }
  852. listnext:=nil;
  853. end;
  854. destructor Tnamedindexobject.done;
  855. begin
  856. stringdispose(_name);
  857. end;
  858. procedure Tnamedindexobject.setname(const n:string);
  859. begin
  860. if speedvalue=-1 then
  861. begin
  862. if assigned(_name) then
  863. stringdispose(_name);
  864. _name:=stringdup(n);
  865. end;
  866. end;
  867. function Tnamedindexobject.name:string;
  868. begin
  869. if assigned(_name) then
  870. name:=_name^
  871. else
  872. name:='';
  873. end;
  874. {****************************************************************************
  875. TDICTIONARY
  876. ****************************************************************************}
  877. constructor Tdictionary.init;
  878. begin
  879. root:=nil;
  880. hasharray:=nil;
  881. noclear:=false;
  882. replace_existing:=false;
  883. end;
  884. procedure Tdictionary.usehash;
  885. begin
  886. if not(assigned(root)) and
  887. not(assigned(hasharray)) then
  888. begin
  889. new(hasharray);
  890. fillchar(hasharray^,sizeof(hasharray^),0);
  891. end;
  892. end;
  893. destructor Tdictionary.done;
  894. begin
  895. if not noclear then
  896. clear;
  897. if assigned(hasharray) then
  898. dispose(hasharray);
  899. end;
  900. procedure Tdictionary.cleartree(obj:Pnamedindexobject);
  901. begin
  902. if assigned(obj^.left) then
  903. cleartree(obj^.left);
  904. if assigned(obj^.right) then
  905. cleartree(obj^.right);
  906. dispose(obj,done);
  907. obj:=nil;
  908. end;
  909. procedure Tdictionary.clear;
  910. var
  911. w : longint;
  912. begin
  913. if assigned(root) then
  914. cleartree(root);
  915. if assigned(hasharray) then
  916. for w:=-hasharraysize to hasharraysize do
  917. if assigned(hasharray^[w]) then
  918. cleartree(hasharray^[w]);
  919. end;
  920. function Tdictionary.delete(const s:string):Pnamedindexobject;
  921. var p,speedvalue:longint;
  922. n:Pnamedindexobject;
  923. procedure insert_right_bottom(var root,Atree:Pnamedindexobject);
  924. begin
  925. while root^.right<>nil do
  926. root:=root^.right;
  927. root^.right:=Atree;
  928. end;
  929. function delete_from_tree(root:Pnamedindexobject):Pnamedindexobject;
  930. type leftright=(left,right);
  931. var lr:leftright;
  932. oldroot:Pnamedindexobject;
  933. begin
  934. oldroot:=nil;
  935. while (root<>nil) and (root^.speedvalue<>speedvalue) do
  936. begin
  937. oldroot:=root;
  938. if speedvalue<root^.speedvalue then
  939. begin
  940. root:=root^.right;
  941. lr:=right;
  942. end
  943. else
  944. begin
  945. root:=root^.left;
  946. lr:=left;
  947. end;
  948. end;
  949. while (root<>nil) and (root^._name^<>s) do
  950. begin
  951. oldroot:=root;
  952. if s<root^._name^ then
  953. begin
  954. root:=root^.right;
  955. lr:=right;
  956. end
  957. else
  958. begin
  959. root:=root^.left;
  960. lr:=left;
  961. end;
  962. end;
  963. if root^.left<>nil then
  964. begin
  965. {Now the node pointing to root must point to the left
  966. subtree of root. The right subtree of root must be
  967. connected to the right bottom of the left subtree.}
  968. if lr=left then
  969. oldroot^.left:=root^.left
  970. else
  971. oldroot^.right:=root^.left;
  972. if root^.right<>nil then
  973. insert_right_bottom(root^.left,root^.right);
  974. end
  975. else
  976. {There is no left subtree. So we can just replace the node to
  977. delete with the right subtree.}
  978. if lr=left then
  979. oldroot^.left:=root^.right
  980. else
  981. oldroot^.right:=root^.right;
  982. delete_from_tree:=root;
  983. end;
  984. begin
  985. speedvalue:=getspeedvalue(s);
  986. n:=root;
  987. if assigned(hasharray) then
  988. begin
  989. {First, check if the node to delete directly located under
  990. the hasharray.}
  991. p:=speedvalue mod hasharraysize;
  992. n:=hasharray^[p];
  993. if (n<>nil) and (n^.speedvalue=speedvalue) and
  994. (n^._name^=s) then
  995. begin
  996. {The node to delete is directly located under the
  997. hasharray. Make the hasharray point to the left
  998. subtree of the node and place the right subtree on
  999. the right-bottom of the left subtree.}
  1000. if n^.left<>nil then
  1001. begin
  1002. hasharray^[p]:=n^.left;
  1003. if n^.right<>nil then
  1004. insert_right_bottom(n^.left,n^.right);
  1005. end
  1006. else
  1007. hasharray^[p]:=n^.right;
  1008. delete:=n;
  1009. exit;
  1010. end;
  1011. end
  1012. else
  1013. begin
  1014. {First check if the node to delete is the root.}
  1015. if (root<>nil) and (n^.speedvalue=speedvalue)
  1016. and (n^._name^=s) then
  1017. begin
  1018. if n^.left<>nil then
  1019. begin
  1020. root:=n^.left;
  1021. if n^.right<>nil then
  1022. insert_right_bottom(n^.left,n^.right);
  1023. end
  1024. else
  1025. root:=n^.right;
  1026. delete:=n;
  1027. exit;
  1028. end;
  1029. end;
  1030. delete:=delete_from_tree(n);
  1031. end;
  1032. function Tdictionary.empty:boolean;
  1033. var
  1034. w : longint;
  1035. begin
  1036. if assigned(hasharray) then
  1037. begin
  1038. empty:=false;
  1039. for w:=-hasharraysize to hasharraysize do
  1040. if assigned(hasharray^[w]) then
  1041. exit;
  1042. empty:=true;
  1043. end
  1044. else
  1045. empty:=(root=nil);
  1046. end;
  1047. procedure Tdictionary.foreach(proc2call:Tnamedindexcallback);
  1048. procedure a(p:Pnamedindexobject);
  1049. begin
  1050. proc2call(p);
  1051. if assigned(p^.left) then
  1052. a(p^.left);
  1053. if assigned(p^.right) then
  1054. a(p^.right);
  1055. end;
  1056. var
  1057. i : longint;
  1058. begin
  1059. if assigned(hasharray) then
  1060. begin
  1061. for i:=-hasharraysize to hasharraysize do
  1062. if assigned(hasharray^[i]) then
  1063. a(hasharray^[i]);
  1064. end
  1065. else
  1066. if assigned(root) then
  1067. a(root);
  1068. end;
  1069. function Tdictionary.insert(obj:Pnamedindexobject):Pnamedindexobject;
  1070. begin
  1071. obj^.speedvalue:=getspeedvalue(obj^._name^);
  1072. if assigned(hasharray) then
  1073. insert:=insertnode(obj,hasharray^[obj^.speedvalue mod hasharraysize])
  1074. else
  1075. insert:=insertnode(obj,root);
  1076. end;
  1077. function tdictionary.insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  1078. begin
  1079. if currnode=nil then
  1080. begin
  1081. currnode:=newnode;
  1082. insertnode:=newnode;
  1083. end
  1084. { first check speedvalue, to allow a fast insert }
  1085. else
  1086. if currnode^.speedvalue>newnode^.speedvalue then
  1087. insertnode:=insertnode(newnode,currnode^.right)
  1088. else
  1089. if currnode^.speedvalue<newnode^.speedvalue then
  1090. insertnode:=insertnode(newnode,currnode^.left)
  1091. else
  1092. begin
  1093. if currnode^._name^>newnode^._name^ then
  1094. insertnode:=insertnode(newnode,currnode^.right)
  1095. else
  1096. if currnode^._name^<newnode^._name^ then
  1097. insertnode:=insertnode(newnode,currnode^.left)
  1098. else
  1099. begin
  1100. if replace_existing and
  1101. assigned(currnode) then
  1102. begin
  1103. newnode^.left:=currnode^.left;
  1104. newnode^.right:=currnode^.right;
  1105. currnode:=newnode;
  1106. insertnode:=newnode;
  1107. end
  1108. else
  1109. insertnode:=currnode;
  1110. end;
  1111. end;
  1112. end;
  1113. procedure tdictionary.inserttree(currtree,currroot:Pnamedindexobject);
  1114. begin
  1115. if assigned(currtree) then
  1116. begin
  1117. inserttree(currtree^.left,currroot);
  1118. inserttree(currtree^.right,currroot);
  1119. currtree^.right:=nil;
  1120. currtree^.left:=nil;
  1121. insertnode(currtree,currroot);
  1122. end;
  1123. end;
  1124. function tdictionary.rename(const olds,news : string):Pnamedindexobject;
  1125. var
  1126. spdval : longint;
  1127. lasthp,
  1128. hp,hp2,hp3 : Pnamedindexobject;
  1129. begin
  1130. spdval:=getspeedvalue(olds);
  1131. if assigned(hasharray) then
  1132. hp:=hasharray^[spdval mod hasharraysize]
  1133. else
  1134. hp:=root;
  1135. lasthp:=nil;
  1136. while assigned(hp) do
  1137. begin
  1138. if spdval>hp^.speedvalue then
  1139. begin
  1140. lasthp:=hp;
  1141. hp:=hp^.left
  1142. end
  1143. else
  1144. if spdval<hp^.speedvalue then
  1145. begin
  1146. lasthp:=hp;
  1147. hp:=hp^.right
  1148. end
  1149. else
  1150. begin
  1151. if (hp^.name=olds) then
  1152. begin
  1153. { get in hp2 the replacer for the root or hasharr }
  1154. hp2:=hp^.left;
  1155. hp3:=hp^.right;
  1156. if not assigned(hp2) then
  1157. begin
  1158. hp2:=hp^.right;
  1159. hp3:=hp^.left;
  1160. end;
  1161. { remove entry from the tree }
  1162. if assigned(lasthp) then
  1163. begin
  1164. if lasthp^.left=hp then
  1165. lasthp^.left:=hp2
  1166. else
  1167. lasthp^.right:=hp2;
  1168. end
  1169. else
  1170. begin
  1171. if assigned(hasharray) then
  1172. hasharray^[spdval mod hasharraysize]:=hp2
  1173. else
  1174. root:=hp2;
  1175. end;
  1176. { reinsert the hp3 in the tree from hp2 }
  1177. inserttree(hp3,hp2);
  1178. { reset node with new values }
  1179. stringdispose(hp^._name);
  1180. hp^._name:=stringdup(news);
  1181. hp^.speedvalue:=getspeedvalue(news);
  1182. hp^.left:=nil;
  1183. hp^.right:=nil;
  1184. { reinsert }
  1185. if assigned(hasharray) then
  1186. rename:=insertnode(hp,hasharray^[hp^.speedvalue mod hasharraysize])
  1187. else
  1188. rename:=insertnode(hp,root);
  1189. exit;
  1190. end
  1191. else
  1192. if olds>hp^.name then
  1193. begin
  1194. lasthp:=hp;
  1195. hp:=hp^.left
  1196. end
  1197. else
  1198. begin
  1199. lasthp:=hp;
  1200. hp:=hp^.right;
  1201. end;
  1202. end;
  1203. end;
  1204. end;
  1205. function Tdictionary.search(const s:string):Pnamedindexobject;
  1206. begin
  1207. search:=speedsearch(s,getspeedvalue(s));
  1208. end;
  1209. function Tdictionary.speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  1210. var
  1211. newnode:Pnamedindexobject;
  1212. begin
  1213. if assigned(hasharray) then
  1214. newnode:=hasharray^[speedvalue mod hasharraysize]
  1215. else
  1216. newnode:=root;
  1217. while assigned(newnode) do
  1218. begin
  1219. if speedvalue>newnode^.speedvalue then
  1220. newnode:=newnode^.left
  1221. else
  1222. if speedvalue<newnode^.speedvalue then
  1223. newnode:=newnode^.right
  1224. else
  1225. begin
  1226. if (newnode^._name^=s) then
  1227. begin
  1228. speedsearch:=newnode;
  1229. exit;
  1230. end
  1231. else
  1232. if s>newnode^._name^ then
  1233. newnode:=newnode^.left
  1234. else
  1235. newnode:=newnode^.right;
  1236. end;
  1237. end;
  1238. speedsearch:=nil;
  1239. end;
  1240. {****************************************************************************
  1241. tsinglelist
  1242. ****************************************************************************}
  1243. constructor tsinglelist.init;
  1244. begin
  1245. first:=nil;
  1246. last:=nil;
  1247. end;
  1248. destructor tsinglelist.done;
  1249. begin
  1250. end;
  1251. procedure tsinglelist.reset;
  1252. begin
  1253. first:=nil;
  1254. last:=nil;
  1255. end;
  1256. procedure tsinglelist.clear;
  1257. var
  1258. hp,hp2 : pnamedindexobject;
  1259. begin
  1260. hp:=first;
  1261. while assigned(hp) do
  1262. begin
  1263. hp2:=hp;
  1264. hp:=hp^.listnext;
  1265. dispose(hp2,done);
  1266. end;
  1267. first:=nil;
  1268. last:=nil;
  1269. end;
  1270. procedure tsinglelist.insert(p:Pnamedindexobject);
  1271. begin
  1272. if not assigned(first) then
  1273. first:=p
  1274. else
  1275. last^.listnext:=p;
  1276. last:=p;
  1277. p^.listnext:=nil;
  1278. end;
  1279. {****************************************************************************
  1280. tdynamicarray
  1281. ****************************************************************************}
  1282. constructor tdynamicarray.init(Ablocksize:longint);
  1283. begin
  1284. posn:=0;
  1285. posnblock:=nil;
  1286. firstblock:=nil;
  1287. lastblock:=nil;
  1288. blocksize:=Ablocksize;
  1289. grow;
  1290. end;
  1291. function tdynamicarray.size:longint;
  1292. begin
  1293. if assigned(lastblock) then
  1294. size:=lastblock^.pos+lastblock^.used
  1295. else
  1296. size:=0;
  1297. end;
  1298. procedure tdynamicarray.grow;
  1299. var
  1300. nblock : pdynamicblock;
  1301. begin
  1302. getmem(nblock,blocksize+dynamicblockbasesize);
  1303. if not assigned(firstblock) then
  1304. begin
  1305. firstblock:=nblock;
  1306. posnblock:=nblock;
  1307. nblock^.pos:=0;
  1308. end
  1309. else
  1310. begin
  1311. lastblock^.next:=nblock;
  1312. nblock^.pos:=lastblock^.pos+lastblock^.used;
  1313. end;
  1314. nblock^.used:=0;
  1315. nblock^.next:=nil;
  1316. fillchar(nblock^.data,blocksize,0);
  1317. lastblock:=nblock;
  1318. end;
  1319. procedure tdynamicarray.align(i:longint);
  1320. var
  1321. j : longint;
  1322. begin
  1323. j:=(posn mod i);
  1324. if j<>0 then
  1325. begin
  1326. j:=i-j;
  1327. if posnblock^.used+j>blocksize then
  1328. begin
  1329. dec(j,blocksize-posnblock^.used);
  1330. posnblock^.used:=blocksize;
  1331. grow;
  1332. posnblock:=lastblock;
  1333. end;
  1334. inc(posnblock^.used,j);
  1335. inc(posn,j);
  1336. end;
  1337. end;
  1338. procedure tdynamicarray.seek(i:longint);
  1339. begin
  1340. if (i<posnblock^.pos) or (i>posnblock^.pos+blocksize) then
  1341. begin
  1342. { set posnblock correct if the size is bigger then
  1343. the current block }
  1344. if posnblock^.pos>i then
  1345. posnblock:=firstblock;
  1346. while assigned(posnblock) do
  1347. begin
  1348. if posnblock^.pos+blocksize>i then
  1349. break;
  1350. posnblock:=posnblock^.next;
  1351. end;
  1352. { not found ? then increase blocks }
  1353. if not assigned(posnblock) then
  1354. begin
  1355. { the current lastblock is now also fully used }
  1356. lastblock^.used:=blocksize;
  1357. repeat
  1358. grow;
  1359. posnblock:=lastblock;
  1360. until posnblock^.pos+blocksize>=i;
  1361. end;
  1362. end;
  1363. posn:=i;
  1364. if posn mod blocksize>posnblock^.used then
  1365. posnblock^.used:=posn mod blocksize;
  1366. end;
  1367. procedure tdynamicarray.write(const d;len:longint);
  1368. var
  1369. p : pchar;
  1370. i,j : longint;
  1371. begin
  1372. p:=pchar(@d);
  1373. while (len>0) do
  1374. begin
  1375. i:=posn mod blocksize;
  1376. if i+len>=blocksize then
  1377. begin
  1378. j:=blocksize-i;
  1379. move(p^,posnblock^.data[i],j);
  1380. inc(p,j);
  1381. inc(posn,j);
  1382. dec(len,j);
  1383. posnblock^.used:=blocksize;
  1384. if assigned(posnblock^.next) then
  1385. posnblock:=posnblock^.next
  1386. else
  1387. begin
  1388. grow;
  1389. posnblock:=lastblock;
  1390. end;
  1391. end
  1392. else
  1393. begin
  1394. move(p^,posnblock^.data[i],len);
  1395. inc(p,len);
  1396. inc(posn,len);
  1397. i:=posn mod blocksize;
  1398. if i>posnblock^.used then
  1399. posnblock^.used:=i;
  1400. len:=0;
  1401. end;
  1402. end;
  1403. end;
  1404. procedure tdynamicarray.writestr(const s:string);
  1405. begin
  1406. write(s[1],length(s));
  1407. end;
  1408. function tdynamicarray.read(var d;len:longint):longint;
  1409. var
  1410. p : pchar;
  1411. i,j,res : longint;
  1412. begin
  1413. res:=0;
  1414. p:=pchar(@d);
  1415. while (len>0) do
  1416. begin
  1417. i:=posn mod blocksize;
  1418. if i+len>=posnblock^.used then
  1419. begin
  1420. j:=posnblock^.used-i;
  1421. move(posnblock^.data[i],p^,j);
  1422. inc(p,j);
  1423. inc(posn,j);
  1424. inc(res,j);
  1425. dec(len,j);
  1426. if assigned(posnblock^.next) then
  1427. posnblock:=posnblock^.next
  1428. else
  1429. break;
  1430. end
  1431. else
  1432. begin
  1433. move(posnblock^.data[i],p^,len);
  1434. inc(p,len);
  1435. inc(posn,len);
  1436. inc(res,len);
  1437. len:=0;
  1438. end;
  1439. end;
  1440. read:=res;
  1441. end;
  1442. procedure tdynamicarray.blockwrite(var f:file);
  1443. var
  1444. hp : pdynamicblock;
  1445. begin
  1446. hp:=firstblock;
  1447. while assigned(hp) do
  1448. begin
  1449. system.blockwrite(f,hp^.data,hp^.used);
  1450. hp:=hp^.next;
  1451. end;
  1452. end;
  1453. destructor tdynamicarray.done;
  1454. var
  1455. hp : pdynamicblock;
  1456. begin
  1457. while assigned(firstblock) do
  1458. begin
  1459. hp:=firstblock;
  1460. firstblock:=firstblock^.next;
  1461. freemem(hp,blocksize+dynamicblockbasesize);
  1462. end;
  1463. end;
  1464. {****************************************************************************
  1465. tindexarray
  1466. ****************************************************************************}
  1467. constructor tindexarray.init(Agrowsize:longint);
  1468. begin
  1469. growsize:=Agrowsize;
  1470. size:=0;
  1471. count:=0;
  1472. data:=nil;
  1473. first:=nil;
  1474. noclear:=false;
  1475. end;
  1476. destructor tindexarray.done;
  1477. begin
  1478. if assigned(data) then
  1479. begin
  1480. if not noclear then
  1481. clear;
  1482. freemem(data,size*4);
  1483. data:=nil;
  1484. end;
  1485. end;
  1486. function tindexarray.search(nr:longint):Pnamedindexobject;
  1487. begin
  1488. if nr<=count then
  1489. search:=data^[nr]
  1490. else
  1491. search:=nil;
  1492. end;
  1493. procedure tindexarray.clear;
  1494. var
  1495. i : longint;
  1496. begin
  1497. for i:=1 to count do
  1498. if assigned(data^[i]) then
  1499. begin
  1500. dispose(data^[i],done);
  1501. data^[i]:=nil;
  1502. end;
  1503. count:=0;
  1504. first:=nil;
  1505. end;
  1506. procedure tindexarray.foreach(proc2call : Tnamedindexcallback);
  1507. var
  1508. i : longint;
  1509. begin
  1510. for i:=1 to count do
  1511. if assigned(data^[i]) then
  1512. proc2call(data^[i]);
  1513. end;
  1514. procedure tindexarray.grow(gsize:longint);
  1515. var
  1516. osize : longint;
  1517. begin
  1518. osize:=size;
  1519. inc(size,gsize);
  1520. reallocmem(data,size*4);
  1521. fillchar(data^[osize+1],gsize*4,0);
  1522. end;
  1523. procedure tindexarray.deleteindex(p:Pnamedindexobject);
  1524. var
  1525. i : longint;
  1526. begin
  1527. i:=p^.indexnr;
  1528. { update counter }
  1529. if i=count then
  1530. dec(count);
  1531. { update linked list }
  1532. while (i>0) do
  1533. begin
  1534. dec(i);
  1535. if (i>0) and assigned(data^[i]) then
  1536. begin
  1537. data^[i]^.indexnext:=data^[p^.indexnr]^.indexnext;
  1538. break;
  1539. end;
  1540. end;
  1541. if i=0 then
  1542. first:=p^.indexnext;
  1543. data^[p^.indexnr]:=nil;
  1544. { clear entry }
  1545. p^.indexnr:=-1;
  1546. p^.indexnext:=nil;
  1547. end;
  1548. procedure tindexarray.delete(var p:Pnamedindexobject);
  1549. begin
  1550. deleteindex(p);
  1551. dispose(p,done);
  1552. p:=nil;
  1553. end;
  1554. procedure tindexarray.insert(p:Pnamedindexobject);
  1555. var
  1556. i : longint;
  1557. begin
  1558. if p^.indexnr=-1 then
  1559. begin
  1560. inc(count);
  1561. p^.indexnr:=count;
  1562. end;
  1563. if p^.indexnr>count then
  1564. count:=p^.indexnr;
  1565. if count>size then
  1566. grow(((count div growsize)+1)*growsize);
  1567. {$ifdef Delphi}
  1568. Assert(not assigned(data^[p^.indexnr]) or (p=data^[p^.indexnr]));
  1569. {$endif}
  1570. data^[p^.indexnr]:=p;
  1571. { update linked list backward }
  1572. i:=p^.indexnr;
  1573. while (i>0) do
  1574. begin
  1575. dec(i);
  1576. if (i>0) and assigned(data^[i]) then
  1577. begin
  1578. data^[i]^.indexnext:=p;
  1579. break;
  1580. end;
  1581. end;
  1582. if i=0 then
  1583. first:=p;
  1584. { update linked list forward }
  1585. i:=p^.indexnr;
  1586. while (i<=count) do
  1587. begin
  1588. inc(i);
  1589. if (i<=count) and assigned(data^[i]) then
  1590. begin
  1591. p^.indexnext:=data^[i];
  1592. exit;
  1593. end;
  1594. end;
  1595. if i>count then
  1596. p^.indexnext:=nil;
  1597. end;
  1598. end.
  1599. {
  1600. $Log$
  1601. Revision 1.19 2000-11-12 22:20:37 peter
  1602. * create generic toutputsection for binary writers
  1603. Revision 1.18 2000/11/04 14:25:19 florian
  1604. + merged Attila's changes for interfaces, not tested yet
  1605. Revision 1.17 2000/11/03 19:41:06 jonas
  1606. * fixed bug in tdynamicarray.align (merged)
  1607. Revision 1.16 2000/10/31 22:02:46 peter
  1608. * symtable splitted, no real code changes
  1609. Revision 1.15 2000/10/14 10:14:46 peter
  1610. * moehrendorf oct 2000 rewrite
  1611. Revision 1.14 2000/09/24 21:19:50 peter
  1612. * delphi compile fixes
  1613. Revision 1.13 2000/09/24 15:06:12 peter
  1614. * use defines.inc
  1615. Revision 1.12 2000/08/27 20:19:38 peter
  1616. * store strings with case in ppu, when an internal symbol is created
  1617. a '$' is prefixed so it's not automatic uppercased
  1618. Revision 1.11 2000/08/27 16:11:50 peter
  1619. * moved some util functions from globals,cobjects to cutils
  1620. * splitted files into finput,fmodule
  1621. Revision 1.10 2000/08/19 18:44:27 peter
  1622. * new tdynamicarray implementation using blocks instead of
  1623. reallocmem (merged)
  1624. Revision 1.9 2000/08/16 18:33:53 peter
  1625. * splitted namedobjectitem.next into indexnext and listnext so it
  1626. can be used in both lists
  1627. * don't allow "word = word" type definitions (merged)
  1628. Revision 1.8 2000/08/13 08:41:57 peter
  1629. * fixed typo in tsinglelist.clear (merged)
  1630. Revision 1.7 2000/08/12 15:34:22 peter
  1631. + usedasmsymbollist to check and reset only the used symbols (merged)
  1632. Revision 1.6 2000/08/10 12:20:44 jonas
  1633. * reallocmem is now also used under Delphi (merged from fixes branch)
  1634. Revision 1.5 2000/08/09 12:09:45 jonas
  1635. * tidexarray and tdynamicarray now use reallocmem() under FPC for
  1636. growing (merged from fixes branch)
  1637. Revision 1.4 2000/08/06 19:42:40 peter
  1638. * removed note
  1639. Revision 1.3 2000/08/02 19:49:58 peter
  1640. * first things for default parameters
  1641. Revision 1.2 2000/07/13 11:32:38 michael
  1642. + removed logs
  1643. }