cobjects.pas 47 KB

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