cobjects.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  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. pmemdebug = ^tmemdebug;
  28. tmemdebug = object
  29. constructor init(const s:string);
  30. destructor done;
  31. procedure show;
  32. private
  33. startmem : longint;
  34. infostr : string[40];
  35. end;
  36. { namedindexobect for use with dictionary and indexarray }
  37. Pnamedindexobject=^Tnamedindexobject;
  38. Tnamedindexobject=object
  39. { indexarray }
  40. indexnr : longint;
  41. indexnext : Pnamedindexobject;
  42. { dictionary }
  43. _name : Pstring;
  44. _valuename : Pstring; { uppercase name }
  45. left,right : Pnamedindexobject;
  46. speedvalue : longint;
  47. { singlelist }
  48. listnext : Pnamedindexobject;
  49. constructor init;
  50. constructor initname(const n:string);
  51. destructor done;virtual;
  52. procedure setname(const n:string);virtual;
  53. function name:string;virtual;
  54. end;
  55. Pdictionaryhasharray=^Tdictionaryhasharray;
  56. Tdictionaryhasharray=array[-hasharraysize..hasharraysize] of Pnamedindexobject;
  57. Tnamedindexcallback = procedure(p:Pnamedindexobject);
  58. Pdictionary=^Tdictionary;
  59. Tdictionary=object
  60. noclear : boolean;
  61. replace_existing : boolean;
  62. constructor init;
  63. destructor done;virtual;
  64. procedure usehash;
  65. procedure clear;
  66. function delete(const s:string):Pnamedindexobject;
  67. function empty:boolean;
  68. procedure foreach(proc2call:Tnamedindexcallback);
  69. function insert(obj:Pnamedindexobject):Pnamedindexobject;
  70. function rename(const olds,news : string):Pnamedindexobject;
  71. function search(const s:string):Pnamedindexobject;
  72. function speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  73. private
  74. root : Pnamedindexobject;
  75. hasharray : Pdictionaryhasharray;
  76. procedure cleartree(obj:Pnamedindexobject);
  77. function insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  78. procedure inserttree(currtree,currroot:Pnamedindexobject);
  79. end;
  80. psinglelist=^tsinglelist;
  81. tsinglelist=object
  82. first,
  83. last : Pnamedindexobject;
  84. constructor init;
  85. destructor done;
  86. procedure reset;
  87. procedure clear;
  88. procedure insert(p:Pnamedindexobject);
  89. end;
  90. tindexobjectarray=array[1..16000] of Pnamedindexobject;
  91. Pnamedindexobjectarray=^tindexobjectarray;
  92. pindexarray=^tindexarray;
  93. tindexarray=object
  94. noclear : boolean;
  95. first : Pnamedindexobject;
  96. count : longint;
  97. constructor init(Agrowsize:longint);
  98. destructor done;
  99. procedure clear;
  100. procedure foreach(proc2call : Tnamedindexcallback);
  101. procedure deleteindex(p:Pnamedindexobject);
  102. procedure delete(var p:Pnamedindexobject);
  103. procedure insert(p:Pnamedindexobject);
  104. function search(nr:longint):Pnamedindexobject;
  105. private
  106. growsize,
  107. size : longint;
  108. data : Pnamedindexobjectarray;
  109. procedure grow(gsize:longint);
  110. end;
  111. {$ifdef fixLeaksOnError}
  112. PStackItem = ^TStackItem;
  113. TStackItem = record
  114. next: PStackItem;
  115. data: pointer;
  116. end;
  117. PStack = ^TStack;
  118. TStack = object
  119. constructor init;
  120. destructor done;
  121. procedure push(p: pointer);
  122. function pop: pointer;
  123. function top: pointer;
  124. function isEmpty: boolean;
  125. private
  126. head: PStackItem;
  127. end;
  128. {$endif fixLeaksOnError}
  129. implementation
  130. {*****************************************************************************
  131. Memory debug
  132. *****************************************************************************}
  133. constructor tmemdebug.init(const s:string);
  134. begin
  135. infostr:=s;
  136. {$ifdef Delphi}
  137. startmem:=0;
  138. {$else}
  139. startmem:=memavail;
  140. {$endif Delphi}
  141. end;
  142. procedure tmemdebug.show;
  143. {$ifndef Delphi}
  144. var
  145. l : longint;
  146. {$endif}
  147. begin
  148. {$ifndef Delphi}
  149. write('memory [',infostr,'] ');
  150. l:=memavail;
  151. if l>startmem then
  152. writeln(l-startmem,' released')
  153. else
  154. writeln(startmem-l,' allocated');
  155. {$endif Delphi}
  156. end;
  157. destructor tmemdebug.done;
  158. begin
  159. show;
  160. end;
  161. {*****************************************************************************
  162. Stack
  163. *****************************************************************************}
  164. {$ifdef fixLeaksOnError}
  165. constructor TStack.init;
  166. begin
  167. head := nil;
  168. end;
  169. procedure TStack.push(p: pointer);
  170. var s: PStackItem;
  171. begin
  172. new(s);
  173. s^.data := p;
  174. s^.next := head;
  175. head := s;
  176. end;
  177. function TStack.pop: pointer;
  178. var s: PStackItem;
  179. begin
  180. pop := top;
  181. if assigned(head) then
  182. begin
  183. s := head^.next;
  184. dispose(head);
  185. head := s;
  186. end
  187. end;
  188. function TStack.top: pointer;
  189. begin
  190. if not isEmpty then
  191. top := head^.data
  192. else top := NIL;
  193. end;
  194. function TStack.isEmpty: boolean;
  195. begin
  196. isEmpty := head = nil;
  197. end;
  198. destructor TStack.done;
  199. var temp: PStackItem;
  200. begin
  201. while head <> nil do
  202. begin
  203. temp := head^.next;
  204. dispose(head);
  205. head := temp;
  206. end;
  207. end;
  208. {$endif fixLeaksOnError}
  209. {****************************************************************************
  210. Tnamedindexobject
  211. ****************************************************************************}
  212. constructor Tnamedindexobject.init;
  213. begin
  214. { index }
  215. indexnr:=-1;
  216. indexnext:=nil;
  217. { dictionary }
  218. left:=nil;
  219. right:=nil;
  220. _name:=nil;
  221. speedvalue:=-1;
  222. { list }
  223. listnext:=nil;
  224. end;
  225. constructor Tnamedindexobject.initname(const n:string);
  226. begin
  227. { index }
  228. indexnr:=-1;
  229. indexnext:=nil;
  230. { dictionary }
  231. left:=nil;
  232. right:=nil;
  233. speedvalue:=-1;
  234. _name:=stringdup(n);
  235. { list }
  236. listnext:=nil;
  237. end;
  238. destructor Tnamedindexobject.done;
  239. begin
  240. stringdispose(_name);
  241. end;
  242. procedure Tnamedindexobject.setname(const n:string);
  243. begin
  244. if speedvalue=-1 then
  245. begin
  246. if assigned(_name) then
  247. stringdispose(_name);
  248. _name:=stringdup(n);
  249. end;
  250. end;
  251. function Tnamedindexobject.name:string;
  252. begin
  253. if assigned(_name) then
  254. name:=_name^
  255. else
  256. name:='';
  257. end;
  258. {****************************************************************************
  259. TDICTIONARY
  260. ****************************************************************************}
  261. constructor Tdictionary.init;
  262. begin
  263. root:=nil;
  264. hasharray:=nil;
  265. noclear:=false;
  266. replace_existing:=false;
  267. end;
  268. procedure Tdictionary.usehash;
  269. begin
  270. if not(assigned(root)) and
  271. not(assigned(hasharray)) then
  272. begin
  273. new(hasharray);
  274. fillchar(hasharray^,sizeof(hasharray^),0);
  275. end;
  276. end;
  277. destructor Tdictionary.done;
  278. begin
  279. if not noclear then
  280. clear;
  281. if assigned(hasharray) then
  282. dispose(hasharray);
  283. end;
  284. procedure Tdictionary.cleartree(obj:Pnamedindexobject);
  285. begin
  286. if assigned(obj^.left) then
  287. cleartree(obj^.left);
  288. if assigned(obj^.right) then
  289. cleartree(obj^.right);
  290. dispose(obj,done);
  291. obj:=nil;
  292. end;
  293. procedure Tdictionary.clear;
  294. var
  295. w : longint;
  296. begin
  297. if assigned(root) then
  298. cleartree(root);
  299. if assigned(hasharray) then
  300. for w:=-hasharraysize to hasharraysize do
  301. if assigned(hasharray^[w]) then
  302. cleartree(hasharray^[w]);
  303. end;
  304. function Tdictionary.delete(const s:string):Pnamedindexobject;
  305. var p,speedvalue:longint;
  306. n:Pnamedindexobject;
  307. procedure insert_right_bottom(var root,Atree:Pnamedindexobject);
  308. begin
  309. while root^.right<>nil do
  310. root:=root^.right;
  311. root^.right:=Atree;
  312. end;
  313. function delete_from_tree(root:Pnamedindexobject):Pnamedindexobject;
  314. type leftright=(left,right);
  315. var lr:leftright;
  316. oldroot:Pnamedindexobject;
  317. begin
  318. oldroot:=nil;
  319. while (root<>nil) and (root^.speedvalue<>speedvalue) do
  320. begin
  321. oldroot:=root;
  322. if speedvalue<root^.speedvalue then
  323. begin
  324. root:=root^.right;
  325. lr:=right;
  326. end
  327. else
  328. begin
  329. root:=root^.left;
  330. lr:=left;
  331. end;
  332. end;
  333. while (root<>nil) and (root^._name^<>s) do
  334. begin
  335. oldroot:=root;
  336. if s<root^._name^ then
  337. begin
  338. root:=root^.right;
  339. lr:=right;
  340. end
  341. else
  342. begin
  343. root:=root^.left;
  344. lr:=left;
  345. end;
  346. end;
  347. if root^.left<>nil then
  348. begin
  349. {Now the node pointing to root must point to the left
  350. subtree of root. The right subtree of root must be
  351. connected to the right bottom of the left subtree.}
  352. if lr=left then
  353. oldroot^.left:=root^.left
  354. else
  355. oldroot^.right:=root^.left;
  356. if root^.right<>nil then
  357. insert_right_bottom(root^.left,root^.right);
  358. end
  359. else
  360. {There is no left subtree. So we can just replace the node to
  361. delete with the right subtree.}
  362. if lr=left then
  363. oldroot^.left:=root^.right
  364. else
  365. oldroot^.right:=root^.right;
  366. delete_from_tree:=root;
  367. end;
  368. begin
  369. speedvalue:=getspeedvalue(s);
  370. n:=root;
  371. if assigned(hasharray) then
  372. begin
  373. {First, check if the node to delete directly located under
  374. the hasharray.}
  375. p:=speedvalue mod hasharraysize;
  376. n:=hasharray^[p];
  377. if (n<>nil) and (n^.speedvalue=speedvalue) and
  378. (n^._name^=s) then
  379. begin
  380. {The node to delete is directly located under the
  381. hasharray. Make the hasharray point to the left
  382. subtree of the node and place the right subtree on
  383. the right-bottom of the left subtree.}
  384. if n^.left<>nil then
  385. begin
  386. hasharray^[p]:=n^.left;
  387. if n^.right<>nil then
  388. insert_right_bottom(n^.left,n^.right);
  389. end
  390. else
  391. hasharray^[p]:=n^.right;
  392. delete:=n;
  393. exit;
  394. end;
  395. end
  396. else
  397. begin
  398. {First check if the node to delete is the root.}
  399. if (root<>nil) and (n^.speedvalue=speedvalue)
  400. and (n^._name^=s) then
  401. begin
  402. if n^.left<>nil then
  403. begin
  404. root:=n^.left;
  405. if n^.right<>nil then
  406. insert_right_bottom(n^.left,n^.right);
  407. end
  408. else
  409. root:=n^.right;
  410. delete:=n;
  411. exit;
  412. end;
  413. end;
  414. delete:=delete_from_tree(n);
  415. end;
  416. function Tdictionary.empty:boolean;
  417. var
  418. w : longint;
  419. begin
  420. if assigned(hasharray) then
  421. begin
  422. empty:=false;
  423. for w:=-hasharraysize to hasharraysize do
  424. if assigned(hasharray^[w]) then
  425. exit;
  426. empty:=true;
  427. end
  428. else
  429. empty:=(root=nil);
  430. end;
  431. procedure Tdictionary.foreach(proc2call:Tnamedindexcallback);
  432. procedure a(p:Pnamedindexobject);
  433. begin
  434. proc2call(p);
  435. if assigned(p^.left) then
  436. a(p^.left);
  437. if assigned(p^.right) then
  438. a(p^.right);
  439. end;
  440. var
  441. i : longint;
  442. begin
  443. if assigned(hasharray) then
  444. begin
  445. for i:=-hasharraysize to hasharraysize do
  446. if assigned(hasharray^[i]) then
  447. a(hasharray^[i]);
  448. end
  449. else
  450. if assigned(root) then
  451. a(root);
  452. end;
  453. function Tdictionary.insert(obj:Pnamedindexobject):Pnamedindexobject;
  454. begin
  455. obj^.speedvalue:=getspeedvalue(obj^._name^);
  456. if assigned(hasharray) then
  457. insert:=insertnode(obj,hasharray^[obj^.speedvalue mod hasharraysize])
  458. else
  459. insert:=insertnode(obj,root);
  460. end;
  461. function tdictionary.insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  462. begin
  463. if currnode=nil then
  464. begin
  465. currnode:=newnode;
  466. insertnode:=newnode;
  467. end
  468. { first check speedvalue, to allow a fast insert }
  469. else
  470. if currnode^.speedvalue>newnode^.speedvalue then
  471. insertnode:=insertnode(newnode,currnode^.right)
  472. else
  473. if currnode^.speedvalue<newnode^.speedvalue then
  474. insertnode:=insertnode(newnode,currnode^.left)
  475. else
  476. begin
  477. if currnode^._name^>newnode^._name^ then
  478. insertnode:=insertnode(newnode,currnode^.right)
  479. else
  480. if currnode^._name^<newnode^._name^ then
  481. insertnode:=insertnode(newnode,currnode^.left)
  482. else
  483. begin
  484. if replace_existing and
  485. assigned(currnode) then
  486. begin
  487. newnode^.left:=currnode^.left;
  488. newnode^.right:=currnode^.right;
  489. currnode:=newnode;
  490. insertnode:=newnode;
  491. end
  492. else
  493. insertnode:=currnode;
  494. end;
  495. end;
  496. end;
  497. procedure tdictionary.inserttree(currtree,currroot:Pnamedindexobject);
  498. begin
  499. if assigned(currtree) then
  500. begin
  501. inserttree(currtree^.left,currroot);
  502. inserttree(currtree^.right,currroot);
  503. currtree^.right:=nil;
  504. currtree^.left:=nil;
  505. insertnode(currtree,currroot);
  506. end;
  507. end;
  508. function tdictionary.rename(const olds,news : string):Pnamedindexobject;
  509. var
  510. spdval : longint;
  511. lasthp,
  512. hp,hp2,hp3 : Pnamedindexobject;
  513. begin
  514. spdval:=getspeedvalue(olds);
  515. if assigned(hasharray) then
  516. hp:=hasharray^[spdval mod hasharraysize]
  517. else
  518. hp:=root;
  519. lasthp:=nil;
  520. while assigned(hp) do
  521. begin
  522. if spdval>hp^.speedvalue then
  523. begin
  524. lasthp:=hp;
  525. hp:=hp^.left
  526. end
  527. else
  528. if spdval<hp^.speedvalue then
  529. begin
  530. lasthp:=hp;
  531. hp:=hp^.right
  532. end
  533. else
  534. begin
  535. if (hp^.name=olds) then
  536. begin
  537. { get in hp2 the replacer for the root or hasharr }
  538. hp2:=hp^.left;
  539. hp3:=hp^.right;
  540. if not assigned(hp2) then
  541. begin
  542. hp2:=hp^.right;
  543. hp3:=hp^.left;
  544. end;
  545. { remove entry from the tree }
  546. if assigned(lasthp) then
  547. begin
  548. if lasthp^.left=hp then
  549. lasthp^.left:=hp2
  550. else
  551. lasthp^.right:=hp2;
  552. end
  553. else
  554. begin
  555. if assigned(hasharray) then
  556. hasharray^[spdval mod hasharraysize]:=hp2
  557. else
  558. root:=hp2;
  559. end;
  560. { reinsert the hp3 in the tree from hp2 }
  561. inserttree(hp3,hp2);
  562. { reset node with new values }
  563. stringdispose(hp^._name);
  564. hp^._name:=stringdup(news);
  565. hp^.speedvalue:=getspeedvalue(news);
  566. hp^.left:=nil;
  567. hp^.right:=nil;
  568. { reinsert }
  569. if assigned(hasharray) then
  570. rename:=insertnode(hp,hasharray^[hp^.speedvalue mod hasharraysize])
  571. else
  572. rename:=insertnode(hp,root);
  573. exit;
  574. end
  575. else
  576. if olds>hp^.name then
  577. begin
  578. lasthp:=hp;
  579. hp:=hp^.left
  580. end
  581. else
  582. begin
  583. lasthp:=hp;
  584. hp:=hp^.right;
  585. end;
  586. end;
  587. end;
  588. end;
  589. function Tdictionary.search(const s:string):Pnamedindexobject;
  590. begin
  591. search:=speedsearch(s,getspeedvalue(s));
  592. end;
  593. function Tdictionary.speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  594. var
  595. newnode:Pnamedindexobject;
  596. begin
  597. if assigned(hasharray) then
  598. newnode:=hasharray^[speedvalue mod hasharraysize]
  599. else
  600. newnode:=root;
  601. while assigned(newnode) do
  602. begin
  603. if speedvalue>newnode^.speedvalue then
  604. newnode:=newnode^.left
  605. else
  606. if speedvalue<newnode^.speedvalue then
  607. newnode:=newnode^.right
  608. else
  609. begin
  610. if (newnode^._name^=s) then
  611. begin
  612. speedsearch:=newnode;
  613. exit;
  614. end
  615. else
  616. if s>newnode^._name^ then
  617. newnode:=newnode^.left
  618. else
  619. newnode:=newnode^.right;
  620. end;
  621. end;
  622. speedsearch:=nil;
  623. end;
  624. {****************************************************************************
  625. tsinglelist
  626. ****************************************************************************}
  627. constructor tsinglelist.init;
  628. begin
  629. first:=nil;
  630. last:=nil;
  631. end;
  632. destructor tsinglelist.done;
  633. begin
  634. end;
  635. procedure tsinglelist.reset;
  636. begin
  637. first:=nil;
  638. last:=nil;
  639. end;
  640. procedure tsinglelist.clear;
  641. var
  642. hp,hp2 : pnamedindexobject;
  643. begin
  644. hp:=first;
  645. while assigned(hp) do
  646. begin
  647. hp2:=hp;
  648. hp:=hp^.listnext;
  649. dispose(hp2,done);
  650. end;
  651. first:=nil;
  652. last:=nil;
  653. end;
  654. procedure tsinglelist.insert(p:Pnamedindexobject);
  655. begin
  656. if not assigned(first) then
  657. first:=p
  658. else
  659. last^.listnext:=p;
  660. last:=p;
  661. p^.listnext:=nil;
  662. end;
  663. {****************************************************************************
  664. tindexarray
  665. ****************************************************************************}
  666. constructor tindexarray.init(Agrowsize:longint);
  667. begin
  668. growsize:=Agrowsize;
  669. size:=0;
  670. count:=0;
  671. data:=nil;
  672. first:=nil;
  673. noclear:=false;
  674. end;
  675. destructor tindexarray.done;
  676. begin
  677. if assigned(data) then
  678. begin
  679. if not noclear then
  680. clear;
  681. freemem(data,size*4);
  682. data:=nil;
  683. end;
  684. end;
  685. function tindexarray.search(nr:longint):Pnamedindexobject;
  686. begin
  687. if nr<=count then
  688. search:=data^[nr]
  689. else
  690. search:=nil;
  691. end;
  692. procedure tindexarray.clear;
  693. var
  694. i : longint;
  695. begin
  696. for i:=1 to count do
  697. if assigned(data^[i]) then
  698. begin
  699. dispose(data^[i],done);
  700. data^[i]:=nil;
  701. end;
  702. count:=0;
  703. first:=nil;
  704. end;
  705. procedure tindexarray.foreach(proc2call : Tnamedindexcallback);
  706. var
  707. i : longint;
  708. begin
  709. for i:=1 to count do
  710. if assigned(data^[i]) then
  711. proc2call(data^[i]);
  712. end;
  713. procedure tindexarray.grow(gsize:longint);
  714. var
  715. osize : longint;
  716. begin
  717. osize:=size;
  718. inc(size,gsize);
  719. reallocmem(data,size*4);
  720. fillchar(data^[osize+1],gsize*4,0);
  721. end;
  722. procedure tindexarray.deleteindex(p:Pnamedindexobject);
  723. var
  724. i : longint;
  725. begin
  726. i:=p^.indexnr;
  727. { update counter }
  728. if i=count then
  729. dec(count);
  730. { update linked list }
  731. while (i>0) do
  732. begin
  733. dec(i);
  734. if (i>0) and assigned(data^[i]) then
  735. begin
  736. data^[i]^.indexnext:=data^[p^.indexnr]^.indexnext;
  737. break;
  738. end;
  739. end;
  740. if i=0 then
  741. first:=p^.indexnext;
  742. data^[p^.indexnr]:=nil;
  743. { clear entry }
  744. p^.indexnr:=-1;
  745. p^.indexnext:=nil;
  746. end;
  747. procedure tindexarray.delete(var p:Pnamedindexobject);
  748. begin
  749. deleteindex(p);
  750. dispose(p,done);
  751. p:=nil;
  752. end;
  753. procedure tindexarray.insert(p:Pnamedindexobject);
  754. var
  755. i : longint;
  756. begin
  757. if p^.indexnr=-1 then
  758. begin
  759. inc(count);
  760. p^.indexnr:=count;
  761. end;
  762. if p^.indexnr>count then
  763. count:=p^.indexnr;
  764. if count>size then
  765. grow(((count div growsize)+1)*growsize);
  766. {$ifdef Delphi}
  767. Assert(not assigned(data^[p^.indexnr]) or (p=data^[p^.indexnr]));
  768. {$endif}
  769. data^[p^.indexnr]:=p;
  770. { update linked list backward }
  771. i:=p^.indexnr;
  772. while (i>0) do
  773. begin
  774. dec(i);
  775. if (i>0) and assigned(data^[i]) then
  776. begin
  777. data^[i]^.indexnext:=p;
  778. break;
  779. end;
  780. end;
  781. if i=0 then
  782. first:=p;
  783. { update linked list forward }
  784. i:=p^.indexnr;
  785. while (i<=count) do
  786. begin
  787. inc(i);
  788. if (i<=count) and assigned(data^[i]) then
  789. begin
  790. p^.indexnext:=data^[i];
  791. exit;
  792. end;
  793. end;
  794. if i>count then
  795. p^.indexnext:=nil;
  796. end;
  797. end.
  798. {
  799. $Log$
  800. Revision 1.22 2000-12-25 00:07:25 peter
  801. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  802. tlinkedlist objects)
  803. Revision 1.21 2000/12/24 12:25:31 peter
  804. + cstreams unit
  805. * dynamicarray object to class
  806. Revision 1.19 2000/11/12 22:20:37 peter
  807. * create generic toutputsection for binary writers
  808. Revision 1.18 2000/11/04 14:25:19 florian
  809. + merged Attila's changes for interfaces, not tested yet
  810. Revision 1.17 2000/11/03 19:41:06 jonas
  811. * fixed bug in tdynamicarray.align (merged)
  812. Revision 1.16 2000/10/31 22:02:46 peter
  813. * symtable splitted, no real code changes
  814. Revision 1.15 2000/10/14 10:14:46 peter
  815. * moehrendorf oct 2000 rewrite
  816. Revision 1.14 2000/09/24 21:19:50 peter
  817. * delphi compile fixes
  818. Revision 1.13 2000/09/24 15:06:12 peter
  819. * use defines.inc
  820. Revision 1.12 2000/08/27 20:19:38 peter
  821. * store strings with case in ppu, when an internal symbol is created
  822. a '$' is prefixed so it's not automatic uppercased
  823. Revision 1.11 2000/08/27 16:11:50 peter
  824. * moved some util functions from globals,cobjects to cutils
  825. * splitted files into finput,fmodule
  826. Revision 1.10 2000/08/19 18:44:27 peter
  827. * new tdynamicarray implementation using blocks instead of
  828. reallocmem (merged)
  829. Revision 1.9 2000/08/16 18:33:53 peter
  830. * splitted namedobjectitem.next into indexnext and listnext so it
  831. can be used in both lists
  832. * don't allow "word = word" type definitions (merged)
  833. Revision 1.8 2000/08/13 08:41:57 peter
  834. * fixed typo in tsinglelist.clear (merged)
  835. Revision 1.7 2000/08/12 15:34:22 peter
  836. + usedasmsymbollist to check and reset only the used symbols (merged)
  837. Revision 1.6 2000/08/10 12:20:44 jonas
  838. * reallocmem is now also used under Delphi (merged from fixes branch)
  839. Revision 1.5 2000/08/09 12:09:45 jonas
  840. * tidexarray and tdynamicarray now use reallocmem() under FPC for
  841. growing (merged from fixes branch)
  842. Revision 1.4 2000/08/06 19:42:40 peter
  843. * removed note
  844. Revision 1.3 2000/08/02 19:49:58 peter
  845. * first things for default parameters
  846. Revision 1.2 2000/07/13 11:32:38 michael
  847. + removed logs
  848. }