cclasses.pas 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl and Peter Vreman
  4. This module provides some basic classes
  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 cclasses;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cutils,cstreams;
  23. {$ifdef OLD}
  24. type
  25. pmemdebug = ^tmemdebug;
  26. tmemdebug = object
  27. constructor init(const s:string);
  28. destructor done;
  29. procedure show;
  30. private
  31. startmem : integer;
  32. infostr : string[40];
  33. end;
  34. {$endif OLD}
  35. {********************************************
  36. TLinkedList
  37. ********************************************}
  38. type
  39. TLinkedListItem = class
  40. public
  41. Previous,
  42. Next : TLinkedListItem;
  43. Constructor Create;
  44. Destructor Destroy;override;
  45. Function GetCopy:TLinkedListItem;virtual;
  46. end;
  47. TLinkedListItemClass = class of TLinkedListItem;
  48. TLinkedList = class
  49. private
  50. FCount : integer;
  51. FFirst,
  52. FLast : TLinkedListItem;
  53. public
  54. constructor Create;
  55. destructor Destroy;override;
  56. { true when the List is empty }
  57. function Empty:boolean;
  58. { deletes all Items }
  59. procedure Clear;
  60. { inserts an Item }
  61. procedure Insert(Item:TLinkedListItem);
  62. { concats an Item }
  63. procedure Concat(Item:TLinkedListItem);
  64. { deletes an Item }
  65. procedure Remove(Item:TLinkedListItem);
  66. { Gets First Item }
  67. function GetFirst:TLinkedListItem;
  68. { Gets last Item }
  69. function GetLast:TLinkedListItem;
  70. { inserts another List at the begin and make this List empty }
  71. procedure insertList(p : TLinkedList);
  72. { concats another List at the end and make this List empty }
  73. procedure concatList(p : TLinkedList);
  74. { concats another List at the end and makes a copy }
  75. procedure insertListcopy(p : TLinkedList);
  76. { concats another List at the end and makes a copy }
  77. procedure concatListcopy(p : TLinkedList);
  78. property First:TLinkedListItem read FFirst;
  79. property Last:TLinkedListItem read FLast;
  80. property Count:Integer read FCount;
  81. end;
  82. {********************************************
  83. TStringList
  84. ********************************************}
  85. { string containerItem }
  86. TStringListItem = class(TLinkedListItem)
  87. FPStr : PString;
  88. public
  89. constructor Create(const s:string);
  90. destructor Destroy;override;
  91. function GetCopy:TLinkedListItem;override;
  92. function Str:string;
  93. end;
  94. { string container }
  95. TStringList = class(TLinkedList)
  96. private
  97. FDoubles : boolean; { if this is set to true, doubles are allowed }
  98. public
  99. constructor Create;
  100. constructor Create_No_Double;
  101. { inserts an Item }
  102. procedure Insert(const s:string);
  103. { concats an Item }
  104. procedure Concat(const s:string);
  105. { deletes an Item }
  106. procedure Remove(const s:string);
  107. { Gets First Item }
  108. function GetFirst:string;
  109. { Gets last Item }
  110. function GetLast:string;
  111. { true if string is in the container }
  112. function Find(const s:string):TStringListItem;
  113. { inserts an object }
  114. procedure InsertItem(item:TStringListItem);
  115. { concats an object }
  116. procedure ConcatItem(item:TStringListItem);
  117. property Doubles:boolean read FDoubles write FDoubles;
  118. end;
  119. {$ifdef NODIC}
  120. {********************************************
  121. Dictionary
  122. ********************************************}
  123. const
  124. { the real size will be [-hasharray..hasharray] ! }
  125. hasharraysize = 2047;
  126. type
  127. { namedindexobect for use with dictionary and indexarray }
  128. Tnamedindexobject=class
  129. { indexarray }
  130. indexnr : integer;
  131. indexNext : TNamedIndexObject;
  132. { dictionary }
  133. _name : Pstring;
  134. _valuename : Pstring; { uppercase name }
  135. left,right : TNamedIndexObject;
  136. speedvalue : integer;
  137. { singleList }
  138. ListNext : TNamedIndexObject;
  139. constructor create;
  140. constructor createname(const n:string);
  141. destructor destroy;override;
  142. procedure setname(const n:string);virtual;
  143. function name:string;virtual;
  144. end;
  145. Pdictionaryhasharray=^Tdictionaryhasharray;
  146. Tdictionaryhasharray=array[-hasharraysize..hasharraysize] of TNamedIndexObject;
  147. Tnamedindexcallback = procedure(p:TNamedIndexObject) of object;
  148. Tdictionary=class
  149. noclear : boolean;
  150. replace_existing : boolean;
  151. constructor Create;
  152. destructor Destroy;override;
  153. procedure usehash;
  154. procedure clear;
  155. function delete(const s:string):TNamedIndexObject;
  156. function empty:boolean;
  157. procedure foreach(proc2call:Tnamedindexcallback);
  158. function insert(obj:TNamedIndexObject):TNamedIndexObject;
  159. function rename(const olds,News : string):TNamedIndexObject;
  160. function search(const s:string):TNamedIndexObject;
  161. function speedsearch(const s:string;speedvalue:integer):TNamedIndexObject;
  162. private
  163. root : TNamedIndexObject;
  164. hasharray : Pdictionaryhasharray;
  165. procedure cleartree(obj:TNamedIndexObject);
  166. function insertNode(NewNode:TNamedIndexObject;var currNode:TNamedIndexObject):TNamedIndexObject;
  167. procedure inserttree(currtree,currroot:TNamedIndexObject);
  168. end;
  169. psingleList=^tsingleList;
  170. tsingleList=class
  171. First,
  172. last : TNamedIndexObject;
  173. constructor Create;
  174. procedure reset;
  175. procedure clear;
  176. procedure insert(p:TNamedIndexObject);
  177. end;
  178. tindexobjectarray=array[1..16000] of TNamedIndexObject;
  179. TNamedIndexObjectarray=^tindexobjectarray;
  180. pindexarray=^tindexarray;
  181. tindexarray=class
  182. noclear : boolean;
  183. First : TNamedIndexObject;
  184. count : integer;
  185. constructor Create(Agrowsize:integer);
  186. destructor destroy;override;
  187. procedure clear;
  188. procedure foreach(proc2call : Tnamedindexcallback);
  189. procedure deleteindex(p:TNamedIndexObject);
  190. procedure delete(var p:TNamedIndexObject);
  191. procedure insert(p:TNamedIndexObject);
  192. function search(nr:integer):TNamedIndexObject;
  193. private
  194. growsize,
  195. size : integer;
  196. data : TNamedIndexObjectarray;
  197. procedure grow(gsize:integer);
  198. end;
  199. {$endif NODIC}
  200. {********************************************
  201. DynamicArray
  202. ********************************************}
  203. const
  204. dynamicblockbasesize = 12;
  205. type
  206. pdynamicblock = ^tdynamicblock;
  207. tdynamicblock = record
  208. pos,
  209. used : integer;
  210. Next : pdynamicblock;
  211. data : array[0..high(integer)-20] of byte;
  212. end;
  213. pdynamicarray = ^tdynamicarray;
  214. tdynamicarray = class
  215. private
  216. FPosn : integer;
  217. FPosnblock : pdynamicblock;
  218. FBlocksize : integer;
  219. FFirstblock,
  220. FLastblock : pdynamicblock;
  221. procedure grow;
  222. public
  223. constructor Create(Ablocksize:integer);
  224. destructor Destroy;override;
  225. function size:integer;
  226. procedure align(i:integer);
  227. procedure seek(i:integer);
  228. function read(var d;len:integer):integer;
  229. procedure write(const d;len:integer);
  230. procedure writestr(const s:string);
  231. procedure readstream(f:TCStream;maxlen:longint);
  232. procedure writestream(f:TCStream);
  233. property BlockSize : integer read FBlocksize;
  234. property FirstBlock : PDynamicBlock read FFirstBlock;
  235. end;
  236. implementation
  237. {$ifdef OLD}
  238. {*****************************************************************************
  239. Memory debug
  240. *****************************************************************************}
  241. constructor tmemdebug.init(const s:string);
  242. begin
  243. infostr:=s;
  244. {$ifdef Delphi}
  245. startmem:=0;
  246. {$else}
  247. startmem:=memavail;
  248. {$endif Delphi}
  249. end;
  250. procedure tmemdebug.show;
  251. {$ifndef Delphi}
  252. var
  253. l : integer;
  254. {$endif}
  255. begin
  256. {$ifndef Delphi}
  257. write('memory [',infostr,'] ');
  258. l:=memavail;
  259. if l>startmem then
  260. writeln(l-startmem,' released')
  261. else
  262. writeln(startmem-l,' allocated');
  263. {$endif Delphi}
  264. end;
  265. destructor tmemdebug.done;
  266. begin
  267. show;
  268. end;
  269. {*****************************************************************************
  270. Stack
  271. *****************************************************************************}
  272. {$ifdef fixLeaksOnError}
  273. constructor TStack.init;
  274. begin
  275. head := nil;
  276. end;
  277. procedure TStack.push(p: pointer);
  278. var s: PStackItem;
  279. begin
  280. New(s);
  281. s^.data := p;
  282. s^.Next := head;
  283. head := s;
  284. end;
  285. function TStack.pop: pointer;
  286. var s: PStackItem;
  287. begin
  288. pop := top;
  289. if assigned(head) then
  290. begin
  291. s := head^.Next;
  292. dispose(head);
  293. head := s;
  294. end
  295. end;
  296. function TStack.top: pointer;
  297. begin
  298. if not isEmpty then
  299. top := head^.data
  300. else top := NIL;
  301. end;
  302. function TStack.isEmpty: boolean;
  303. begin
  304. isEmpty := head = nil;
  305. end;
  306. destructor TStack.done;
  307. var temp: PStackItem;
  308. begin
  309. while head <> nil do
  310. begin
  311. temp := head^.Next;
  312. dispose(head);
  313. head := temp;
  314. end;
  315. end;
  316. {$endif fixLeaksOnError}
  317. {$endif OLD}
  318. {****************************************************************************
  319. TLinkedListItem
  320. ****************************************************************************}
  321. constructor TLinkedListItem.Create;
  322. begin
  323. Previous:=nil;
  324. Next:=nil;
  325. end;
  326. destructor TLinkedListItem.Destroy;
  327. begin
  328. end;
  329. function TLinkedListItem.GetCopy:TLinkedListItem;
  330. var
  331. p : TLinkedListItem;
  332. l : integer;
  333. begin
  334. p:=TLinkedListItemClass(ClassType).Create;
  335. l:=InstanceSize;
  336. Move(pointer(self)^,pointer(p)^,l);
  337. Result:=p;
  338. end;
  339. {****************************************************************************
  340. TLinkedList
  341. ****************************************************************************}
  342. constructor TLinkedList.Create;
  343. begin
  344. FFirst:=nil;
  345. Flast:=nil;
  346. FCount:=0;
  347. end;
  348. destructor TLinkedList.destroy;
  349. begin
  350. Clear;
  351. end;
  352. function TLinkedList.empty:boolean;
  353. begin
  354. Empty:=(FFirst=nil);
  355. end;
  356. procedure TLinkedList.Insert(Item:TLinkedListItem);
  357. begin
  358. if FFirst=nil then
  359. begin
  360. FLast:=Item;
  361. Item.Previous:=nil;
  362. Item.Next:=nil;
  363. end
  364. else
  365. begin
  366. FFirst.Previous:=Item;
  367. Item.Previous:=nil;
  368. Item.Next:=FFirst;
  369. end;
  370. FFirst:=Item;
  371. inc(FCount);
  372. end;
  373. procedure TLinkedList.Concat(Item:TLinkedListItem);
  374. begin
  375. if FFirst=nil then
  376. begin
  377. FFirst:=Item;
  378. Item.Previous:=nil;
  379. Item.Next:=nil;
  380. end
  381. else
  382. begin
  383. Flast.Next:=Item;
  384. Item.Previous:=Flast;
  385. Item.Next:=nil;
  386. end;
  387. Flast:=Item;
  388. inc(FCount);
  389. end;
  390. procedure TLinkedList.remove(Item:TLinkedListItem);
  391. begin
  392. if Item=nil then
  393. exit;
  394. if (FFirst=Item) and (Flast=Item) then
  395. begin
  396. FFirst:=nil;
  397. Flast:=nil;
  398. end
  399. else if FFirst=Item then
  400. begin
  401. FFirst:=Item.Next;
  402. if assigned(FFirst) then
  403. FFirst.Previous:=nil;
  404. end
  405. else if Flast=Item then
  406. begin
  407. Flast:=Flast.Previous;
  408. if assigned(Flast) then
  409. Flast.Next:=nil;
  410. end
  411. else
  412. begin
  413. Item.Previous.Next:=Item.Next;
  414. Item.Next.Previous:=Item.Previous;
  415. end;
  416. Item.Next:=nil;
  417. Item.Previous:=nil;
  418. dec(FCount);
  419. end;
  420. procedure TLinkedList.clear;
  421. var
  422. NewNode : TLinkedListItem;
  423. begin
  424. NewNode:=FFirst;
  425. while assigned(NewNode) do
  426. begin
  427. FFirst:=NewNode.Next;
  428. NewNode.Free;
  429. NewNode:=FFirst;
  430. end;
  431. FLast:=nil;
  432. FFirst:=nil;
  433. FCount:=0;
  434. end;
  435. function TLinkedList.GetFirst:TLinkedListItem;
  436. begin
  437. if FFirst=nil then
  438. GetFirst:=nil
  439. else
  440. begin
  441. GetFirst:=FFirst;
  442. if FFirst=FLast then
  443. FLast:=nil;
  444. FFirst:=FFirst.Next;
  445. dec(FCount);
  446. end;
  447. end;
  448. function TLinkedList.GetLast:TLinkedListItem;
  449. begin
  450. if FLast=nil then
  451. Getlast:=nil
  452. else
  453. begin
  454. Getlast:=FLast;
  455. if FLast=FFirst then
  456. FFirst:=nil;
  457. FLast:=FLast.Previous;
  458. dec(FCount);
  459. end;
  460. end;
  461. procedure TLinkedList.insertList(p : TLinkedList);
  462. begin
  463. { empty List ? }
  464. if (p.FFirst=nil) then
  465. exit;
  466. p.Flast.Next:=FFirst;
  467. { we have a double Linked List }
  468. if assigned(FFirst) then
  469. FFirst.Previous:=p.Flast;
  470. FFirst:=p.FFirst;
  471. if (FLast=nil) then
  472. Flast:=p.Flast;
  473. { p becomes empty }
  474. p.FFirst:=nil;
  475. p.Flast:=nil;
  476. end;
  477. procedure TLinkedList.concatList(p : TLinkedList);
  478. begin
  479. if (p.FFirst=nil) then
  480. exit;
  481. if FFirst=nil then
  482. FFirst:=p.FFirst
  483. else
  484. begin
  485. FLast.Next:=p.FFirst;
  486. p.FFirst.Previous:=Flast;
  487. end;
  488. Flast:=p.Flast;
  489. { make p empty }
  490. p.Flast:=nil;
  491. p.FFirst:=nil;
  492. end;
  493. procedure TLinkedList.insertListcopy(p : TLinkedList);
  494. var
  495. NewNode,NewNode2 : TLinkedListItem;
  496. begin
  497. NewNode:=p.First;
  498. while assigned(NewNode) do
  499. begin
  500. NewNode2:=NewNode.Getcopy;
  501. if assigned(NewNode2) then
  502. Insert(NewNode2);
  503. NewNode:=NewNode.Next;
  504. end;
  505. end;
  506. procedure TLinkedList.concatListcopy(p : TLinkedList);
  507. var
  508. NewNode,NewNode2 : TLinkedListItem;
  509. begin
  510. NewNode:=p.First;
  511. while assigned(NewNode) do
  512. begin
  513. NewNode2:=NewNode.Getcopy;
  514. if assigned(NewNode2) then
  515. Concat(NewNode2);
  516. NewNode:=NewNode.Next;
  517. end;
  518. end;
  519. {****************************************************************************
  520. TStringListItem
  521. ****************************************************************************}
  522. constructor TStringListItem.Create(const s:string);
  523. begin
  524. inherited Create;
  525. FPStr:=stringdup(s);
  526. end;
  527. destructor TStringListItem.Destroy;
  528. begin
  529. stringdispose(FPStr);
  530. end;
  531. function TStringListItem.Str:string;
  532. begin
  533. Str:=FPStr^;
  534. end;
  535. function TStringListItem.GetCopy:TLinkedListItem;
  536. begin
  537. Result:=(inherited GetCopy);
  538. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  539. end;
  540. {****************************************************************************
  541. TSTRINGList
  542. ****************************************************************************}
  543. constructor tstringList.Create;
  544. begin
  545. inherited Create;
  546. FDoubles:=true;
  547. end;
  548. constructor tstringList.Create_no_double;
  549. begin
  550. inherited Create;
  551. FDoubles:=false;
  552. end;
  553. procedure tstringList.insert(const s : string);
  554. begin
  555. if (s='') or
  556. ((not FDoubles) and (find(s)<>nil)) then
  557. exit;
  558. inherited insert(tstringListItem.create(s));
  559. end;
  560. procedure tstringList.concat(const s : string);
  561. begin
  562. if (s='') or
  563. ((not FDoubles) and (find(s)<>nil)) then
  564. exit;
  565. inherited concat(tstringListItem.create(s));
  566. end;
  567. procedure tstringList.remove(const s : string);
  568. var
  569. p : tstringListItem;
  570. begin
  571. if s='' then
  572. exit;
  573. p:=find(s);
  574. if assigned(p) then
  575. begin
  576. inherited Remove(p);
  577. p.Free;
  578. end;
  579. end;
  580. function tstringList.GetFirst : string;
  581. var
  582. p : tstringListItem;
  583. begin
  584. p:=tstringListItem(inherited GetFirst);
  585. if p=nil then
  586. GetFirst:=''
  587. else
  588. begin
  589. GetFirst:=p.FPStr^;
  590. p.free;
  591. end;
  592. end;
  593. function tstringList.Getlast : string;
  594. var
  595. p : tstringListItem;
  596. begin
  597. p:=tstringListItem(inherited Getlast);
  598. if p=nil then
  599. Getlast:=''
  600. else
  601. begin
  602. Getlast:=p.FPStr^;
  603. p.free;
  604. end;
  605. end;
  606. function tstringList.find(const s:string):TstringListItem;
  607. var
  608. NewNode : tstringListItem;
  609. begin
  610. find:=nil;
  611. if s='' then
  612. exit;
  613. NewNode:=tstringListItem(FFirst);
  614. while assigned(NewNode) do
  615. begin
  616. if NewNode.FPStr^=s then
  617. begin
  618. find:=NewNode;
  619. exit;
  620. end;
  621. NewNode:=tstringListItem(NewNode.Next);
  622. end;
  623. end;
  624. procedure TStringList.InsertItem(item:TStringListItem);
  625. begin
  626. inherited Insert(item);
  627. end;
  628. procedure TStringList.ConcatItem(item:TStringListItem);
  629. begin
  630. inherited Concat(item);
  631. end;
  632. {$ifdef NODIC}
  633. {****************************************************************************
  634. Tnamedindexobject
  635. ****************************************************************************}
  636. constructor Tnamedindexobject.Create;
  637. begin
  638. { index }
  639. indexnr:=-1;
  640. indexNext:=nil;
  641. { dictionary }
  642. left:=nil;
  643. right:=nil;
  644. _name:=nil;
  645. speedvalue:=-1;
  646. { List }
  647. ListNext:=nil;
  648. end;
  649. constructor Tnamedindexobject.Createname(const n:string);
  650. begin
  651. { index }
  652. indexnr:=-1;
  653. indexNext:=nil;
  654. { dictionary }
  655. left:=nil;
  656. right:=nil;
  657. speedvalue:=-1;
  658. _name:=stringdup(n);
  659. { List }
  660. ListNext:=nil;
  661. end;
  662. destructor Tnamedindexobject.destroy;
  663. begin
  664. stringdispose(_name);
  665. end;
  666. procedure Tnamedindexobject.setname(const n:string);
  667. begin
  668. if speedvalue=-1 then
  669. begin
  670. if assigned(_name) then
  671. stringdispose(_name);
  672. _name:=stringdup(n);
  673. end;
  674. end;
  675. function Tnamedindexobject.name:string;
  676. begin
  677. if assigned(_name) then
  678. name:=_name^
  679. else
  680. name:='';
  681. end;
  682. {****************************************************************************
  683. TDICTIONARY
  684. ****************************************************************************}
  685. constructor Tdictionary.Create;
  686. begin
  687. root:=nil;
  688. hasharray:=nil;
  689. noclear:=false;
  690. replace_existing:=false;
  691. end;
  692. procedure Tdictionary.usehash;
  693. begin
  694. if not(assigned(root)) and
  695. not(assigned(hasharray)) then
  696. begin
  697. New(hasharray);
  698. fillchar(hasharray^,sizeof(hasharray^),0);
  699. end;
  700. end;
  701. destructor Tdictionary.destroy;
  702. begin
  703. if not noclear then
  704. clear;
  705. if assigned(hasharray) then
  706. dispose(hasharray);
  707. end;
  708. procedure Tdictionary.cleartree(obj:TNamedIndexObject);
  709. begin
  710. if assigned(obj.left) then
  711. cleartree(obj.left);
  712. if assigned(obj.right) then
  713. cleartree(obj.right);
  714. obj.free;
  715. obj:=nil;
  716. end;
  717. procedure Tdictionary.clear;
  718. var
  719. w : integer;
  720. begin
  721. if assigned(root) then
  722. cleartree(root);
  723. if assigned(hasharray) then
  724. for w:=-hasharraysize to hasharraysize do
  725. if assigned(hasharray^[w]) then
  726. cleartree(hasharray^[w]);
  727. end;
  728. function Tdictionary.delete(const s:string):TNamedIndexObject;
  729. var
  730. p,speedvalue : integer;
  731. n : TNamedIndexObject;
  732. procedure insert_right_bottom(var root,Atree:TNamedIndexObject);
  733. begin
  734. while root.right<>nil do
  735. root:=root.right;
  736. root.right:=Atree;
  737. end;
  738. function delete_from_tree(root:TNamedIndexObject):TNamedIndexObject;
  739. type
  740. leftright=(left,right);
  741. var
  742. lr : leftright;
  743. oldroot : TNamedIndexObject;
  744. begin
  745. oldroot:=nil;
  746. while (root<>nil) and (root.speedvalue<>speedvalue) do
  747. begin
  748. oldroot:=root;
  749. if speedvalue<root.speedvalue then
  750. begin
  751. root:=root.right;
  752. lr:=right;
  753. end
  754. else
  755. begin
  756. root:=root.left;
  757. lr:=left;
  758. end;
  759. end;
  760. while (root<>nil) and (root._name^<>s) do
  761. begin
  762. oldroot:=root;
  763. if s<root._name^ then
  764. begin
  765. root:=root.right;
  766. lr:=right;
  767. end
  768. else
  769. begin
  770. root:=root.left;
  771. lr:=left;
  772. end;
  773. end;
  774. if root.left<>nil then
  775. begin
  776. { Now the Node pointing to root must point to the left
  777. subtree of root. The right subtree of root must be
  778. connected to the right bottom of the left subtree.}
  779. if lr=left then
  780. oldroot.left:=root.left
  781. else
  782. oldroot.right:=root.left;
  783. if root.right<>nil then
  784. insert_right_bottom(root.left,root.right);
  785. end
  786. else
  787. begin
  788. { There is no left subtree. So we can just replace the Node to
  789. delete with the right subtree.}
  790. if lr=left then
  791. oldroot.left:=root.right
  792. else
  793. oldroot.right:=root.right;
  794. end;
  795. delete_from_tree:=root;
  796. end;
  797. begin
  798. speedvalue:=Getspeedvalue(s);
  799. n:=root;
  800. if assigned(hasharray) then
  801. begin
  802. { First, check if the Node to delete directly located under
  803. the hasharray.}
  804. p:=speedvalue mod hasharraysize;
  805. n:=hasharray^[p];
  806. if (n<>nil) and (n.speedvalue=speedvalue) and
  807. (n._name^=s) then
  808. begin
  809. { The Node to delete is directly located under the
  810. hasharray. Make the hasharray point to the left
  811. subtree of the Node and place the right subtree on
  812. the right-bottom of the left subtree.}
  813. if n.left<>nil then
  814. begin
  815. hasharray^[p]:=n.left;
  816. if n.right<>nil then
  817. insert_right_bottom(n.left,n.right);
  818. end
  819. else
  820. hasharray^[p]:=n.right;
  821. delete:=n;
  822. exit;
  823. end;
  824. end
  825. else
  826. begin
  827. { First check if the Node to delete is the root.}
  828. if (root<>nil) and (n.speedvalue=speedvalue) and
  829. (n._name^=s) then
  830. begin
  831. if n.left<>nil then
  832. begin
  833. root:=n.left;
  834. if n.right<>nil then
  835. insert_right_bottom(n.left,n.right);
  836. end
  837. else
  838. root:=n.right;
  839. delete:=n;
  840. exit;
  841. end;
  842. end;
  843. delete:=delete_from_tree(n);
  844. end;
  845. function Tdictionary.empty:boolean;
  846. var
  847. w : integer;
  848. begin
  849. if assigned(hasharray) then
  850. begin
  851. empty:=false;
  852. for w:=-hasharraysize to hasharraysize do
  853. if assigned(hasharray^[w]) then
  854. exit;
  855. empty:=true;
  856. end
  857. else
  858. empty:=(root=nil);
  859. end;
  860. procedure Tdictionary.foreach(proc2call:Tnamedindexcallback);
  861. procedure a(p:TNamedIndexObject);
  862. begin
  863. proc2call(p);
  864. if assigned(p.left) then
  865. a(p.left);
  866. if assigned(p.right) then
  867. a(p.right);
  868. end;
  869. var
  870. i : integer;
  871. begin
  872. if assigned(hasharray) then
  873. begin
  874. for i:=-hasharraysize to hasharraysize do
  875. if assigned(hasharray^[i]) then
  876. a(hasharray^[i]);
  877. end
  878. else
  879. if assigned(root) then
  880. a(root);
  881. end;
  882. function Tdictionary.insert(obj:TNamedIndexObject):TNamedIndexObject;
  883. begin
  884. obj.speedvalue:=Getspeedvalue(obj._name^);
  885. if assigned(hasharray) then
  886. insert:=insertNode(obj,hasharray^[obj.speedvalue mod hasharraysize])
  887. else
  888. insert:=insertNode(obj,root);
  889. end;
  890. function tdictionary.insertNode(NewNode:TNamedIndexObject;var currNode:TNamedIndexObject):TNamedIndexObject;
  891. begin
  892. if currNode=nil then
  893. begin
  894. currNode:=NewNode;
  895. insertNode:=NewNode;
  896. end
  897. { First check speedvalue, to allow a fast insert }
  898. else
  899. if currNode.speedvalue>NewNode.speedvalue then
  900. insertNode:=insertNode(NewNode,currNode.right)
  901. else
  902. if currNode.speedvalue<NewNode.speedvalue then
  903. insertNode:=insertNode(NewNode,currNode.left)
  904. else
  905. begin
  906. if currNode._name^>NewNode._name^ then
  907. insertNode:=insertNode(NewNode,currNode.right)
  908. else
  909. if currNode._name^<NewNode._name^ then
  910. insertNode:=insertNode(NewNode,currNode.left)
  911. else
  912. begin
  913. if replace_existing and
  914. assigned(currNode) then
  915. begin
  916. NewNode.left:=currNode.left;
  917. NewNode.right:=currNode.right;
  918. currNode:=NewNode;
  919. insertNode:=NewNode;
  920. end
  921. else
  922. insertNode:=currNode;
  923. end;
  924. end;
  925. end;
  926. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexObject);
  927. begin
  928. if assigned(currtree) then
  929. begin
  930. inserttree(currtree.left,currroot);
  931. inserttree(currtree.right,currroot);
  932. currtree.right:=nil;
  933. currtree.left:=nil;
  934. insertNode(currtree,currroot);
  935. end;
  936. end;
  937. function tdictionary.rename(const olds,News : string):TNamedIndexObject;
  938. var
  939. spdval : integer;
  940. lasthp,
  941. hp,hp2,hp3 : TNamedIndexObject;
  942. begin
  943. spdval:=Getspeedvalue(olds);
  944. if assigned(hasharray) then
  945. hp:=hasharray^[spdval mod hasharraysize]
  946. else
  947. hp:=root;
  948. lasthp:=nil;
  949. while assigned(hp) do
  950. begin
  951. if spdval>hp.speedvalue then
  952. begin
  953. lasthp:=hp;
  954. hp:=hp.left
  955. end
  956. else
  957. if spdval<hp.speedvalue then
  958. begin
  959. lasthp:=hp;
  960. hp:=hp.right
  961. end
  962. else
  963. begin
  964. if (hp.name=olds) then
  965. begin
  966. { Get in hp2 the replacer for the root or hasharr }
  967. hp2:=hp.left;
  968. hp3:=hp.right;
  969. if not assigned(hp2) then
  970. begin
  971. hp2:=hp.right;
  972. hp3:=hp.left;
  973. end;
  974. { remove entry from the tree }
  975. if assigned(lasthp) then
  976. begin
  977. if lasthp.left=hp then
  978. lasthp.left:=hp2
  979. else
  980. lasthp.right:=hp2;
  981. end
  982. else
  983. begin
  984. if assigned(hasharray) then
  985. hasharray^[spdval mod hasharraysize]:=hp2
  986. else
  987. root:=hp2;
  988. end;
  989. { reinsert the hp3 in the tree from hp2 }
  990. inserttree(hp3,hp2);
  991. { reset Node with New values }
  992. stringdispose(hp._name);
  993. hp._name:=stringdup(News);
  994. hp.speedvalue:=Getspeedvalue(News);
  995. hp.left:=nil;
  996. hp.right:=nil;
  997. { reinsert }
  998. if assigned(hasharray) then
  999. rename:=insertNode(hp,hasharray^[hp.speedvalue mod hasharraysize])
  1000. else
  1001. rename:=insertNode(hp,root);
  1002. exit;
  1003. end
  1004. else
  1005. if olds>hp.name then
  1006. begin
  1007. lasthp:=hp;
  1008. hp:=hp.left
  1009. end
  1010. else
  1011. begin
  1012. lasthp:=hp;
  1013. hp:=hp.right;
  1014. end;
  1015. end;
  1016. end;
  1017. end;
  1018. function Tdictionary.search(const s:string):TNamedIndexObject;
  1019. begin
  1020. search:=speedsearch(s,Getspeedvalue(s));
  1021. end;
  1022. function Tdictionary.speedsearch(const s:string;speedvalue:integer):TNamedIndexObject;
  1023. var
  1024. NewNode:TNamedIndexObject;
  1025. begin
  1026. if assigned(hasharray) then
  1027. NewNode:=hasharray^[speedvalue mod hasharraysize]
  1028. else
  1029. NewNode:=root;
  1030. while assigned(NewNode) do
  1031. begin
  1032. if speedvalue>NewNode.speedvalue then
  1033. NewNode:=NewNode.left
  1034. else
  1035. if speedvalue<NewNode.speedvalue then
  1036. NewNode:=NewNode.right
  1037. else
  1038. begin
  1039. if (NewNode._name^=s) then
  1040. begin
  1041. speedsearch:=NewNode;
  1042. exit;
  1043. end
  1044. else
  1045. if s>NewNode._name^ then
  1046. NewNode:=NewNode.left
  1047. else
  1048. NewNode:=NewNode.right;
  1049. end;
  1050. end;
  1051. speedsearch:=nil;
  1052. end;
  1053. {****************************************************************************
  1054. tsingleList
  1055. ****************************************************************************}
  1056. constructor tsingleList.create;
  1057. begin
  1058. First:=nil;
  1059. last:=nil;
  1060. end;
  1061. procedure tsingleList.reset;
  1062. begin
  1063. First:=nil;
  1064. last:=nil;
  1065. end;
  1066. procedure tsingleList.clear;
  1067. var
  1068. hp,hp2 : TNamedIndexObject;
  1069. begin
  1070. hp:=First;
  1071. while assigned(hp) do
  1072. begin
  1073. hp2:=hp;
  1074. hp:=hp.ListNext;
  1075. hp2.free;
  1076. end;
  1077. First:=nil;
  1078. last:=nil;
  1079. end;
  1080. procedure tsingleList.insert(p:TNamedIndexObject);
  1081. begin
  1082. if not assigned(First) then
  1083. First:=p
  1084. else
  1085. last.ListNext:=p;
  1086. last:=p;
  1087. p.ListNext:=nil;
  1088. end;
  1089. {****************************************************************************
  1090. tindexarray
  1091. ****************************************************************************}
  1092. constructor tindexarray.create(Agrowsize:integer);
  1093. begin
  1094. growsize:=Agrowsize;
  1095. size:=0;
  1096. count:=0;
  1097. data:=nil;
  1098. First:=nil;
  1099. noclear:=false;
  1100. end;
  1101. destructor tindexarray.destroy;
  1102. begin
  1103. if assigned(data) then
  1104. begin
  1105. if not noclear then
  1106. clear;
  1107. freemem(data);
  1108. data:=nil;
  1109. end;
  1110. end;
  1111. function tindexarray.search(nr:integer):TNamedIndexObject;
  1112. begin
  1113. if nr<=count then
  1114. search:=data^[nr]
  1115. else
  1116. search:=nil;
  1117. end;
  1118. procedure tindexarray.clear;
  1119. var
  1120. i : integer;
  1121. begin
  1122. for i:=1 to count do
  1123. if assigned(data^[i]) then
  1124. begin
  1125. data^[i].free;
  1126. data^[i]:=nil;
  1127. end;
  1128. count:=0;
  1129. First:=nil;
  1130. end;
  1131. procedure tindexarray.foreach(proc2call : Tnamedindexcallback);
  1132. var
  1133. i : integer;
  1134. begin
  1135. for i:=1 to count do
  1136. if assigned(data^[i]) then
  1137. proc2call(data^[i]);
  1138. end;
  1139. procedure tindexarray.grow(gsize:integer);
  1140. var
  1141. osize : integer;
  1142. begin
  1143. osize:=size;
  1144. inc(size,gsize);
  1145. reallocmem(data,size*4);
  1146. fillchar(data^[osize+1],gsize*4,0);
  1147. end;
  1148. procedure tindexarray.deleteindex(p:TNamedIndexObject);
  1149. var
  1150. i : integer;
  1151. begin
  1152. i:=p.indexnr;
  1153. { update counter }
  1154. if i=count then
  1155. dec(count);
  1156. { update Linked List }
  1157. while (i>0) do
  1158. begin
  1159. dec(i);
  1160. if (i>0) and assigned(data^[i]) then
  1161. begin
  1162. data^[i].indexNext:=data^[p.indexnr].indexNext;
  1163. break;
  1164. end;
  1165. end;
  1166. if i=0 then
  1167. First:=p.indexNext;
  1168. data^[p.indexnr]:=nil;
  1169. { clear entry }
  1170. p.indexnr:=-1;
  1171. p.indexNext:=nil;
  1172. end;
  1173. procedure tindexarray.delete(var p:TNamedIndexObject);
  1174. begin
  1175. deleteindex(p);
  1176. p.free;
  1177. p:=nil;
  1178. end;
  1179. procedure tindexarray.insert(p:TNamedIndexObject);
  1180. var
  1181. i : integer;
  1182. begin
  1183. if p.indexnr=-1 then
  1184. begin
  1185. inc(count);
  1186. p.indexnr:=count;
  1187. end;
  1188. if p.indexnr>count then
  1189. count:=p.indexnr;
  1190. if count>size then
  1191. grow(((count div growsize)+1)*growsize);
  1192. Assert(not assigned(data^[p.indexnr]) or (p=data^[p.indexnr]));
  1193. data^[p.indexnr]:=p;
  1194. { update Linked List backward }
  1195. i:=p.indexnr;
  1196. while (i>0) do
  1197. begin
  1198. dec(i);
  1199. if (i>0) and assigned(data^[i]) then
  1200. begin
  1201. data^[i].indexNext:=p;
  1202. break;
  1203. end;
  1204. end;
  1205. if i=0 then
  1206. First:=p;
  1207. { update Linked List forward }
  1208. i:=p.indexnr;
  1209. while (i<=count) do
  1210. begin
  1211. inc(i);
  1212. if (i<=count) and assigned(data^[i]) then
  1213. begin
  1214. p.indexNext:=data^[i];
  1215. exit;
  1216. end;
  1217. end;
  1218. if i>count then
  1219. p.indexNext:=nil;
  1220. end;
  1221. {$endif NODIC}
  1222. {****************************************************************************
  1223. tdynamicarray
  1224. ****************************************************************************}
  1225. constructor tdynamicarray.create(Ablocksize:integer);
  1226. begin
  1227. FPosn:=0;
  1228. FPosnblock:=nil;
  1229. FFirstblock:=nil;
  1230. FLastblock:=nil;
  1231. Fblocksize:=Ablocksize;
  1232. grow;
  1233. end;
  1234. destructor tdynamicarray.destroy;
  1235. var
  1236. hp : pdynamicblock;
  1237. begin
  1238. while assigned(FFirstblock) do
  1239. begin
  1240. hp:=FFirstblock;
  1241. FFirstblock:=FFirstblock^.Next;
  1242. freemem(hp,blocksize+dynamicblockbasesize);
  1243. end;
  1244. end;
  1245. function tdynamicarray.size:integer;
  1246. begin
  1247. if assigned(FLastblock) then
  1248. size:=FLastblock^.pos+FLastblock^.used
  1249. else
  1250. size:=0;
  1251. end;
  1252. procedure tdynamicarray.grow;
  1253. var
  1254. nblock : pdynamicblock;
  1255. begin
  1256. Getmem(nblock,blocksize+dynamicblockbasesize);
  1257. if not assigned(FFirstblock) then
  1258. begin
  1259. FFirstblock:=nblock;
  1260. FPosnblock:=nblock;
  1261. nblock^.pos:=0;
  1262. end
  1263. else
  1264. begin
  1265. FLastblock^.Next:=nblock;
  1266. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1267. end;
  1268. nblock^.used:=0;
  1269. nblock^.Next:=nil;
  1270. fillchar(nblock^.data,blocksize,0);
  1271. FLastblock:=nblock;
  1272. end;
  1273. procedure tdynamicarray.align(i:integer);
  1274. var
  1275. j : integer;
  1276. begin
  1277. j:=(FPosn mod i);
  1278. if j<>0 then
  1279. begin
  1280. j:=i-j;
  1281. if FPosnblock^.used+j>blocksize then
  1282. begin
  1283. dec(j,blocksize-FPosnblock^.used);
  1284. FPosnblock^.used:=blocksize;
  1285. grow;
  1286. FPosnblock:=FLastblock;
  1287. end;
  1288. inc(FPosnblock^.used,j);
  1289. inc(FPosn,j);
  1290. end;
  1291. end;
  1292. procedure tdynamicarray.seek(i:integer);
  1293. begin
  1294. if (i<FPosnblock^.pos) or (i>FPosnblock^.pos+blocksize) then
  1295. begin
  1296. { set FPosnblock correct if the size is bigger then
  1297. the current block }
  1298. if FPosnblock^.pos>i then
  1299. FPosnblock:=FFirstblock;
  1300. while assigned(FPosnblock) do
  1301. begin
  1302. if FPosnblock^.pos+blocksize>i then
  1303. break;
  1304. FPosnblock:=FPosnblock^.Next;
  1305. end;
  1306. { not found ? then increase blocks }
  1307. if not assigned(FPosnblock) then
  1308. begin
  1309. { the current FLastblock is now also fully used }
  1310. FLastblock^.used:=blocksize;
  1311. repeat
  1312. grow;
  1313. FPosnblock:=FLastblock;
  1314. until FPosnblock^.pos+blocksize>=i;
  1315. end;
  1316. end;
  1317. FPosn:=i;
  1318. if FPosn mod blocksize>FPosnblock^.used then
  1319. FPosnblock^.used:=FPosn mod blocksize;
  1320. end;
  1321. procedure tdynamicarray.write(const d;len:integer);
  1322. var
  1323. p : pchar;
  1324. i,j : integer;
  1325. begin
  1326. p:=pchar(@d);
  1327. while (len>0) do
  1328. begin
  1329. i:=FPosn mod blocksize;
  1330. if i+len>=blocksize then
  1331. begin
  1332. j:=blocksize-i;
  1333. move(p^,FPosnblock^.data[i],j);
  1334. inc(p,j);
  1335. inc(FPosn,j);
  1336. dec(len,j);
  1337. FPosnblock^.used:=blocksize;
  1338. if assigned(FPosnblock^.Next) then
  1339. FPosnblock:=FPosnblock^.Next
  1340. else
  1341. begin
  1342. grow;
  1343. FPosnblock:=FLastblock;
  1344. end;
  1345. end
  1346. else
  1347. begin
  1348. move(p^,FPosnblock^.data[i],len);
  1349. inc(p,len);
  1350. inc(FPosn,len);
  1351. i:=FPosn mod blocksize;
  1352. if i>FPosnblock^.used then
  1353. FPosnblock^.used:=i;
  1354. len:=0;
  1355. end;
  1356. end;
  1357. end;
  1358. procedure tdynamicarray.writestr(const s:string);
  1359. begin
  1360. write(s[1],length(s));
  1361. end;
  1362. function tdynamicarray.read(var d;len:integer):integer;
  1363. var
  1364. p : pchar;
  1365. i,j,res : integer;
  1366. begin
  1367. res:=0;
  1368. p:=pchar(@d);
  1369. while (len>0) do
  1370. begin
  1371. i:=FPosn mod blocksize;
  1372. if i+len>=FPosnblock^.used then
  1373. begin
  1374. j:=FPosnblock^.used-i;
  1375. move(FPosnblock^.data[i],p^,j);
  1376. inc(p,j);
  1377. inc(FPosn,j);
  1378. inc(res,j);
  1379. dec(len,j);
  1380. if assigned(FPosnblock^.Next) then
  1381. FPosnblock:=FPosnblock^.Next
  1382. else
  1383. break;
  1384. end
  1385. else
  1386. begin
  1387. move(FPosnblock^.data[i],p^,len);
  1388. inc(p,len);
  1389. inc(FPosn,len);
  1390. inc(res,len);
  1391. len:=0;
  1392. end;
  1393. end;
  1394. read:=res;
  1395. end;
  1396. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  1397. var
  1398. i,left : integer;
  1399. begin
  1400. if maxlen=-1 then
  1401. maxlen:=maxlongint;
  1402. repeat
  1403. left:=blocksize-FPosnblock^.used;
  1404. if left>maxlen then
  1405. left:=maxlen;
  1406. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  1407. dec(maxlen,i);
  1408. inc(FPosnblock^.used,i);
  1409. if FPosnblock^.used=blocksize then
  1410. begin
  1411. if assigned(FPosnblock^.Next) then
  1412. FPosnblock:=FPosnblock^.Next
  1413. else
  1414. begin
  1415. grow;
  1416. FPosnblock:=FLastblock;
  1417. end;
  1418. end;
  1419. until (i<left) or (maxlen=0);
  1420. end;
  1421. procedure tdynamicarray.writestream(f:TCStream);
  1422. var
  1423. hp : pdynamicblock;
  1424. begin
  1425. hp:=FFirstblock;
  1426. while assigned(hp) do
  1427. begin
  1428. f.Write(hp^.data,hp^.used);
  1429. hp:=hp^.Next;
  1430. end;
  1431. end;
  1432. end.
  1433. {
  1434. $Log$
  1435. Revision 1.5 2001-03-13 18:45:06 peter
  1436. * fixed some memory leaks
  1437. Revision 1.4 2001/03/05 21:40:01 peter
  1438. * fixed tdynamicarray.readstream
  1439. Revision 1.3 2000/12/29 21:57:27 peter
  1440. * 'classified' tdictionary, but leave it within an define
  1441. Revision 1.2 2000/12/25 00:07:25 peter
  1442. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1443. tlinkedlist objects)
  1444. Revision 1.1 2000/12/24 12:25:31 peter
  1445. + cstreams unit
  1446. * dynamicarray object to class
  1447. }