cobjects.pas 48 KB

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