cobjects.pas 26 KB

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