cobjects.pas 47 KB

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