cclasses.pas 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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 fpcdefs.inc}
  20. interface
  21. uses
  22. cutils,cstreams;
  23. {********************************************
  24. TMemDebug
  25. ********************************************}
  26. type
  27. tmemdebug = class
  28. private
  29. totalmem,
  30. startmem : integer;
  31. infostr : string[40];
  32. public
  33. constructor Create(const s:string);
  34. destructor Destroy;override;
  35. procedure show;
  36. procedure start;
  37. procedure stop;
  38. end;
  39. {********************************************
  40. TLinkedList
  41. ********************************************}
  42. type
  43. TLinkedListItem = class
  44. public
  45. Previous,
  46. Next : TLinkedListItem;
  47. Constructor Create;
  48. Destructor Destroy;override;
  49. Function GetCopy:TLinkedListItem;virtual;
  50. end;
  51. TLinkedListItemClass = class of TLinkedListItem;
  52. TLinkedList = class
  53. private
  54. FCount : integer;
  55. FFirst,
  56. FLast : TLinkedListItem;
  57. FNoClear : boolean;
  58. public
  59. constructor Create;
  60. destructor Destroy;override;
  61. { true when the List is empty }
  62. function Empty:boolean;
  63. { deletes all Items }
  64. procedure Clear;
  65. { inserts an Item }
  66. procedure Insert(Item:TLinkedListItem);
  67. { concats an Item }
  68. procedure Concat(Item:TLinkedListItem);
  69. { deletes an Item }
  70. procedure Remove(Item:TLinkedListItem);
  71. { Gets First Item }
  72. function GetFirst:TLinkedListItem;
  73. { Gets last Item }
  74. function GetLast:TLinkedListItem;
  75. { inserts another List at the begin and make this List empty }
  76. procedure insertList(p : TLinkedList);
  77. { concats another List at the end and make this List empty }
  78. procedure concatList(p : TLinkedList);
  79. { concats another List at the start and makes a copy
  80. the list is ordered in reverse.
  81. }
  82. procedure insertListcopy(p : TLinkedList);
  83. { concats another List at the end and makes a copy }
  84. procedure concatListcopy(p : TLinkedList);
  85. property First:TLinkedListItem read FFirst;
  86. property Last:TLinkedListItem read FLast;
  87. property Count:Integer read FCount;
  88. property NoClear:boolean write FNoClear;
  89. end;
  90. {********************************************
  91. TStringList
  92. ********************************************}
  93. { string containerItem }
  94. TStringListItem = class(TLinkedListItem)
  95. FPStr : PString;
  96. public
  97. constructor Create(const s:string);
  98. destructor Destroy;override;
  99. function GetCopy:TLinkedListItem;override;
  100. function Str:string;
  101. end;
  102. { string container }
  103. TStringList = class(TLinkedList)
  104. private
  105. FDoubles : boolean; { if this is set to true, doubles are allowed }
  106. public
  107. constructor Create;
  108. constructor Create_No_Double;
  109. { inserts an Item }
  110. procedure Insert(const s:string);
  111. { concats an Item }
  112. procedure Concat(const s:string);
  113. { deletes an Item }
  114. procedure Remove(const s:string);
  115. { Gets First Item }
  116. function GetFirst:string;
  117. { Gets last Item }
  118. function GetLast:string;
  119. { true if string is in the container }
  120. function Find(const s:string):TStringListItem;
  121. { inserts an item }
  122. procedure InsertItem(item:TStringListItem);
  123. { concats an item }
  124. procedure ConcatItem(item:TStringListItem);
  125. property Doubles:boolean read FDoubles write FDoubles;
  126. end;
  127. {********************************************
  128. Dictionary
  129. ********************************************}
  130. const
  131. { the real size will be [0..hasharray-1] ! }
  132. hasharraysize = 512;
  133. type
  134. { namedindexobect for use with dictionary and indexarray }
  135. TNamedIndexItem=class
  136. private
  137. { indexarray }
  138. FIndexNr : integer;
  139. FIndexNext : TNamedIndexItem;
  140. { dictionary }
  141. FLeft,
  142. FRight : TNamedIndexItem;
  143. FSpeedValue : cardinal;
  144. { singleList }
  145. FListNext : TNamedIndexItem;
  146. protected
  147. function GetName:string;virtual;
  148. procedure SetName(const n:string);virtual;
  149. public
  150. FName : Pstring;
  151. constructor Create;
  152. constructor CreateName(const n:string);
  153. destructor Destroy;override;
  154. property IndexNr:integer read FIndexNr write FIndexNr;
  155. property IndexNext:TNamedIndexItem read FIndexNext write FIndexNext;
  156. property Name:string read GetName write SetName;
  157. property SpeedValue:cardinal read FSpeedValue;
  158. property ListNext:TNamedIndexItem read FListNext;
  159. property Left:TNamedIndexItem read FLeft write FLeft;
  160. property Right:TNamedIndexItem read FRight write FRight;
  161. end;
  162. Pdictionaryhasharray=^Tdictionaryhasharray;
  163. Tdictionaryhasharray=array[0..hasharraysize-1] of TNamedIndexItem;
  164. TnamedIndexCallback = procedure(p:TNamedIndexItem;arg:pointer) of object;
  165. TnamedIndexStaticCallback = procedure(p:TNamedIndexItem;arg:pointer);
  166. Tdictionary=class
  167. private
  168. FRoot : TNamedIndexItem;
  169. FHashArray : Pdictionaryhasharray;
  170. procedure cleartree(var obj:TNamedIndexItem);
  171. function insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  172. procedure inserttree(currtree,currroot:TNamedIndexItem);
  173. public
  174. noclear : boolean;
  175. delete_doubles : boolean;
  176. constructor Create;
  177. destructor Destroy;override;
  178. procedure usehash;
  179. procedure clear;
  180. function delete(const s:string):TNamedIndexItem;
  181. function empty:boolean;
  182. procedure foreach(proc2call:TNamedIndexcallback;arg:pointer);
  183. procedure foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  184. function insert(obj:TNamedIndexItem):TNamedIndexItem;
  185. function replace(oldobj,newobj:TNamedIndexItem):boolean;
  186. function rename(const olds,News : string):TNamedIndexItem;
  187. function search(const s:string):TNamedIndexItem;
  188. function speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  189. property Items[const s:string]:TNamedIndexItem read Search;default;
  190. end;
  191. tsingleList=class
  192. First,
  193. last : TNamedIndexItem;
  194. constructor Create;
  195. procedure reset;
  196. procedure clear;
  197. procedure insert(p:TNamedIndexItem);
  198. end;
  199. tindexobjectarray=array[1..16000] of TNamedIndexItem;
  200. pnamedindexobjectarray=^tindexobjectarray;
  201. tindexarray=class
  202. noclear : boolean;
  203. First : TNamedIndexItem;
  204. count : integer;
  205. constructor Create(Agrowsize:integer);
  206. destructor destroy;override;
  207. procedure clear;
  208. procedure foreach(proc2call : Tnamedindexcallback;arg:pointer);
  209. procedure foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  210. procedure deleteindex(p:TNamedIndexItem);
  211. procedure delete(var p:TNamedIndexItem);
  212. procedure insert(p:TNamedIndexItem);
  213. procedure replace(oldp,newp:TNamedIndexItem);
  214. function search(nr:integer):TNamedIndexItem;
  215. private
  216. growsize,
  217. size : integer;
  218. data : pnamedindexobjectarray;
  219. procedure grow(gsize:integer);
  220. end;
  221. {********************************************
  222. DynamicArray
  223. ********************************************}
  224. const
  225. dynamicblockbasesize = 12;
  226. type
  227. pdynamicblock = ^tdynamicblock;
  228. tdynamicblock = record
  229. pos,
  230. used : integer;
  231. Next : pdynamicblock;
  232. data : array[0..high(integer)-20] of byte;
  233. end;
  234. tdynamicarray = class
  235. private
  236. FPosn : integer;
  237. FPosnblock : pdynamicblock;
  238. FBlocksize : integer;
  239. FFirstblock,
  240. FLastblock : pdynamicblock;
  241. procedure grow;
  242. public
  243. constructor Create(Ablocksize:integer);
  244. destructor Destroy;override;
  245. function size:integer;
  246. procedure align(i:integer);
  247. procedure seek(i:integer);
  248. function read(var d;len:integer):integer;
  249. procedure write(const d;len:integer);
  250. procedure writestr(const s:string);
  251. procedure readstream(f:TCStream;maxlen:longint);
  252. procedure writestream(f:TCStream);
  253. property BlockSize : integer read FBlocksize;
  254. property FirstBlock : PDynamicBlock read FFirstBlock;
  255. end;
  256. implementation
  257. {*****************************************************************************
  258. Memory debug
  259. *****************************************************************************}
  260. constructor tmemdebug.create(const s:string);
  261. begin
  262. infostr:=s;
  263. totalmem:=0;
  264. Start;
  265. end;
  266. procedure tmemdebug.start;
  267. begin
  268. {$ifdef Delphi}
  269. startmem:=0;
  270. {$else}
  271. startmem:=memavail;
  272. {$endif Delphi}
  273. end;
  274. procedure tmemdebug.stop;
  275. begin
  276. if startmem<>0 then
  277. begin
  278. {$ifndef Delphi}
  279. inc(TotalMem,memavail-startmem);
  280. {$endif}
  281. startmem:=0;
  282. end;
  283. end;
  284. destructor tmemdebug.destroy;
  285. begin
  286. Stop;
  287. show;
  288. end;
  289. procedure tmemdebug.show;
  290. begin
  291. {$ifndef Delphi}
  292. write('memory [',infostr,'] ');
  293. if TotalMem>0 then
  294. writeln(DStr(TotalMem shr 10),' Kb released')
  295. else
  296. writeln(DStr((-TotalMem) shr 10),' Kb allocated');
  297. {$endif Delphi}
  298. end;
  299. {*****************************************************************************
  300. Stack
  301. *****************************************************************************}
  302. {$ifdef fixLeaksOnError}
  303. constructor TStack.init;
  304. begin
  305. head := nil;
  306. end;
  307. procedure TStack.push(p: pointer);
  308. var s: PStackItem;
  309. begin
  310. New(s);
  311. s^.data := p;
  312. s^.Next := head;
  313. head := s;
  314. end;
  315. function TStack.pop: pointer;
  316. var s: PStackItem;
  317. begin
  318. pop := top;
  319. if assigned(head) then
  320. begin
  321. s := head^.Next;
  322. dispose(head);
  323. head := s;
  324. end
  325. end;
  326. function TStack.top: pointer;
  327. begin
  328. if not isEmpty then
  329. top := head^.data
  330. else top := NIL;
  331. end;
  332. function TStack.isEmpty: boolean;
  333. begin
  334. isEmpty := head = nil;
  335. end;
  336. destructor TStack.done;
  337. var temp: PStackItem;
  338. begin
  339. while head <> nil do
  340. begin
  341. temp := head^.Next;
  342. dispose(head);
  343. head := temp;
  344. end;
  345. end;
  346. {$endif fixLeaksOnError}
  347. {****************************************************************************
  348. TLinkedListItem
  349. ****************************************************************************}
  350. constructor TLinkedListItem.Create;
  351. begin
  352. Previous:=nil;
  353. Next:=nil;
  354. end;
  355. destructor TLinkedListItem.Destroy;
  356. begin
  357. end;
  358. function TLinkedListItem.GetCopy:TLinkedListItem;
  359. var
  360. p : TLinkedListItem;
  361. l : integer;
  362. begin
  363. p:=TLinkedListItemClass(ClassType).Create;
  364. l:=InstanceSize;
  365. Move(pointer(self)^,pointer(p)^,l);
  366. Result:=p;
  367. end;
  368. {****************************************************************************
  369. TLinkedList
  370. ****************************************************************************}
  371. constructor TLinkedList.Create;
  372. begin
  373. FFirst:=nil;
  374. Flast:=nil;
  375. FCount:=0;
  376. FNoClear:=False;
  377. end;
  378. destructor TLinkedList.destroy;
  379. begin
  380. if not FNoClear then
  381. Clear;
  382. end;
  383. function TLinkedList.empty:boolean;
  384. begin
  385. Empty:=(FFirst=nil);
  386. end;
  387. procedure TLinkedList.Insert(Item:TLinkedListItem);
  388. begin
  389. if FFirst=nil then
  390. begin
  391. FLast:=Item;
  392. Item.Previous:=nil;
  393. Item.Next:=nil;
  394. end
  395. else
  396. begin
  397. FFirst.Previous:=Item;
  398. Item.Previous:=nil;
  399. Item.Next:=FFirst;
  400. end;
  401. FFirst:=Item;
  402. inc(FCount);
  403. end;
  404. procedure TLinkedList.Concat(Item:TLinkedListItem);
  405. begin
  406. if FFirst=nil then
  407. begin
  408. FFirst:=Item;
  409. Item.Previous:=nil;
  410. Item.Next:=nil;
  411. end
  412. else
  413. begin
  414. Flast.Next:=Item;
  415. Item.Previous:=Flast;
  416. Item.Next:=nil;
  417. end;
  418. Flast:=Item;
  419. inc(FCount);
  420. end;
  421. procedure TLinkedList.remove(Item:TLinkedListItem);
  422. begin
  423. if Item=nil then
  424. exit;
  425. if (FFirst=Item) and (Flast=Item) then
  426. begin
  427. FFirst:=nil;
  428. Flast:=nil;
  429. end
  430. else if FFirst=Item then
  431. begin
  432. FFirst:=Item.Next;
  433. if assigned(FFirst) then
  434. FFirst.Previous:=nil;
  435. end
  436. else if Flast=Item then
  437. begin
  438. Flast:=Flast.Previous;
  439. if assigned(Flast) then
  440. Flast.Next:=nil;
  441. end
  442. else
  443. begin
  444. Item.Previous.Next:=Item.Next;
  445. Item.Next.Previous:=Item.Previous;
  446. end;
  447. Item.Next:=nil;
  448. Item.Previous:=nil;
  449. dec(FCount);
  450. end;
  451. procedure TLinkedList.clear;
  452. var
  453. NewNode : TLinkedListItem;
  454. begin
  455. NewNode:=FFirst;
  456. while assigned(NewNode) do
  457. begin
  458. FFirst:=NewNode.Next;
  459. NewNode.Free;
  460. NewNode:=FFirst;
  461. end;
  462. FLast:=nil;
  463. FFirst:=nil;
  464. FCount:=0;
  465. end;
  466. function TLinkedList.GetFirst:TLinkedListItem;
  467. begin
  468. if FFirst=nil then
  469. GetFirst:=nil
  470. else
  471. begin
  472. GetFirst:=FFirst;
  473. if FFirst=FLast then
  474. FLast:=nil;
  475. FFirst:=FFirst.Next;
  476. dec(FCount);
  477. end;
  478. end;
  479. function TLinkedList.GetLast:TLinkedListItem;
  480. begin
  481. if FLast=nil then
  482. Getlast:=nil
  483. else
  484. begin
  485. Getlast:=FLast;
  486. if FLast=FFirst then
  487. FFirst:=nil;
  488. FLast:=FLast.Previous;
  489. dec(FCount);
  490. end;
  491. end;
  492. procedure TLinkedList.insertList(p : TLinkedList);
  493. begin
  494. { empty List ? }
  495. if (p.FFirst=nil) then
  496. exit;
  497. p.Flast.Next:=FFirst;
  498. { we have a double Linked List }
  499. if assigned(FFirst) then
  500. FFirst.Previous:=p.Flast;
  501. FFirst:=p.FFirst;
  502. if (FLast=nil) then
  503. Flast:=p.Flast;
  504. { p becomes empty }
  505. p.FFirst:=nil;
  506. p.Flast:=nil;
  507. end;
  508. procedure TLinkedList.concatList(p : TLinkedList);
  509. begin
  510. if (p.FFirst=nil) then
  511. exit;
  512. if FFirst=nil then
  513. FFirst:=p.FFirst
  514. else
  515. begin
  516. FLast.Next:=p.FFirst;
  517. p.FFirst.Previous:=Flast;
  518. end;
  519. Flast:=p.Flast;
  520. { make p empty }
  521. p.Flast:=nil;
  522. p.FFirst:=nil;
  523. end;
  524. procedure TLinkedList.insertListcopy(p : TLinkedList);
  525. var
  526. NewNode,NewNode2 : TLinkedListItem;
  527. begin
  528. NewNode:=p.First;
  529. while assigned(NewNode) do
  530. begin
  531. NewNode2:=NewNode.Getcopy;
  532. if assigned(NewNode2) then
  533. Insert(NewNode2);
  534. NewNode:=NewNode.Next;
  535. end;
  536. end;
  537. procedure TLinkedList.concatListcopy(p : TLinkedList);
  538. var
  539. NewNode,NewNode2 : TLinkedListItem;
  540. begin
  541. NewNode:=p.First;
  542. while assigned(NewNode) do
  543. begin
  544. NewNode2:=NewNode.Getcopy;
  545. if assigned(NewNode2) then
  546. Concat(NewNode2);
  547. NewNode:=NewNode.Next;
  548. end;
  549. end;
  550. {****************************************************************************
  551. TStringListItem
  552. ****************************************************************************}
  553. constructor TStringListItem.Create(const s:string);
  554. begin
  555. inherited Create;
  556. FPStr:=stringdup(s);
  557. end;
  558. destructor TStringListItem.Destroy;
  559. begin
  560. stringdispose(FPStr);
  561. end;
  562. function TStringListItem.Str:string;
  563. begin
  564. Str:=FPStr^;
  565. end;
  566. function TStringListItem.GetCopy:TLinkedListItem;
  567. begin
  568. Result:=(inherited GetCopy);
  569. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  570. end;
  571. {****************************************************************************
  572. TSTRINGList
  573. ****************************************************************************}
  574. constructor tstringList.Create;
  575. begin
  576. inherited Create;
  577. FDoubles:=true;
  578. end;
  579. constructor tstringList.Create_no_double;
  580. begin
  581. inherited Create;
  582. FDoubles:=false;
  583. end;
  584. procedure tstringList.insert(const s : string);
  585. begin
  586. if (s='') or
  587. ((not FDoubles) and (find(s)<>nil)) then
  588. exit;
  589. inherited insert(tstringListItem.create(s));
  590. end;
  591. procedure tstringList.concat(const s : string);
  592. begin
  593. if (s='') or
  594. ((not FDoubles) and (find(s)<>nil)) then
  595. exit;
  596. inherited concat(tstringListItem.create(s));
  597. end;
  598. procedure tstringList.remove(const s : string);
  599. var
  600. p : tstringListItem;
  601. begin
  602. if s='' then
  603. exit;
  604. p:=find(s);
  605. if assigned(p) then
  606. begin
  607. inherited Remove(p);
  608. p.Free;
  609. end;
  610. end;
  611. function tstringList.GetFirst : string;
  612. var
  613. p : tstringListItem;
  614. begin
  615. p:=tstringListItem(inherited GetFirst);
  616. if p=nil then
  617. GetFirst:=''
  618. else
  619. begin
  620. GetFirst:=p.FPStr^;
  621. p.free;
  622. end;
  623. end;
  624. function tstringList.Getlast : string;
  625. var
  626. p : tstringListItem;
  627. begin
  628. p:=tstringListItem(inherited Getlast);
  629. if p=nil then
  630. Getlast:=''
  631. else
  632. begin
  633. Getlast:=p.FPStr^;
  634. p.free;
  635. end;
  636. end;
  637. function tstringList.find(const s:string):TstringListItem;
  638. var
  639. NewNode : tstringListItem;
  640. begin
  641. find:=nil;
  642. if s='' then
  643. exit;
  644. NewNode:=tstringListItem(FFirst);
  645. while assigned(NewNode) do
  646. begin
  647. if NewNode.FPStr^=s then
  648. begin
  649. find:=NewNode;
  650. exit;
  651. end;
  652. NewNode:=tstringListItem(NewNode.Next);
  653. end;
  654. end;
  655. procedure TStringList.InsertItem(item:TStringListItem);
  656. begin
  657. inherited Insert(item);
  658. end;
  659. procedure TStringList.ConcatItem(item:TStringListItem);
  660. begin
  661. inherited Concat(item);
  662. end;
  663. {****************************************************************************
  664. TNamedIndexItem
  665. ****************************************************************************}
  666. constructor TNamedIndexItem.Create;
  667. begin
  668. { index }
  669. Findexnr:=-1;
  670. FindexNext:=nil;
  671. { dictionary }
  672. Fleft:=nil;
  673. Fright:=nil;
  674. FName:=nil;
  675. Fspeedvalue:=cardinal($ffffffff);
  676. { List }
  677. FListNext:=nil;
  678. end;
  679. constructor TNamedIndexItem.Createname(const n:string);
  680. begin
  681. { index }
  682. Findexnr:=-1;
  683. FindexNext:=nil;
  684. { dictionary }
  685. Fleft:=nil;
  686. Fright:=nil;
  687. Fspeedvalue:=cardinal($ffffffff);
  688. FName:=stringdup(n);
  689. { List }
  690. FListNext:=nil;
  691. end;
  692. destructor TNamedIndexItem.destroy;
  693. begin
  694. stringdispose(FName);
  695. end;
  696. procedure TNamedIndexItem.setname(const n:string);
  697. begin
  698. if speedvalue=cardinal($ffffffff) then
  699. begin
  700. if assigned(FName) then
  701. stringdispose(FName);
  702. FName:=stringdup(n);
  703. end;
  704. end;
  705. function TNamedIndexItem.GetName:string;
  706. begin
  707. if assigned(FName) then
  708. Getname:=FName^
  709. else
  710. Getname:='';
  711. end;
  712. {****************************************************************************
  713. TDICTIONARY
  714. ****************************************************************************}
  715. constructor Tdictionary.Create;
  716. begin
  717. FRoot:=nil;
  718. FHashArray:=nil;
  719. noclear:=false;
  720. delete_doubles:=false;
  721. end;
  722. procedure Tdictionary.usehash;
  723. begin
  724. if not(assigned(FRoot)) and
  725. not(assigned(FHashArray)) then
  726. begin
  727. New(FHashArray);
  728. fillchar(FHashArray^,sizeof(FHashArray^),0);
  729. end;
  730. end;
  731. function counttree(p: tnamedindexitem): longint;
  732. begin
  733. counttree:=0;
  734. if not assigned(p) then
  735. exit;
  736. result := 1;
  737. inc(result,counttree(p.fleft));
  738. inc(result,counttree(p.fright));
  739. end;
  740. destructor Tdictionary.destroy;
  741. begin
  742. if not noclear then
  743. clear;
  744. if assigned(FHashArray) then
  745. begin
  746. dispose(FHashArray);
  747. end;
  748. end;
  749. procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
  750. begin
  751. if assigned(obj.Fleft) then
  752. cleartree(obj.FLeft);
  753. if assigned(obj.FRight) then
  754. cleartree(obj.FRight);
  755. obj.free;
  756. obj:=nil;
  757. end;
  758. procedure Tdictionary.clear;
  759. var
  760. w : integer;
  761. begin
  762. if assigned(FRoot) then
  763. cleartree(FRoot);
  764. if assigned(FHashArray) then
  765. for w:= low(FHashArray^) to high(FHashArray^) do
  766. if assigned(FHashArray^[w]) then
  767. cleartree(FHashArray^[w]);
  768. end;
  769. function Tdictionary.delete(const s:string):TNamedIndexItem;
  770. var
  771. p,SpeedValue : cardinal;
  772. n : TNamedIndexItem;
  773. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  774. begin
  775. while root.FRight<>nil do
  776. root:=root.FRight;
  777. root.FRight:=Atree;
  778. end;
  779. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  780. type
  781. leftright=(left,right);
  782. var
  783. lr : leftright;
  784. oldroot : TNamedIndexItem;
  785. begin
  786. oldroot:=nil;
  787. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  788. begin
  789. oldroot:=root;
  790. if SpeedValue<root.SpeedValue then
  791. begin
  792. root:=root.FRight;
  793. lr:=right;
  794. end
  795. else
  796. begin
  797. root:=root.FLeft;
  798. lr:=left;
  799. end;
  800. end;
  801. while (root<>nil) and (root.FName^<>s) do
  802. begin
  803. oldroot:=root;
  804. if s<root.FName^ then
  805. begin
  806. root:=root.FRight;
  807. lr:=right;
  808. end
  809. else
  810. begin
  811. root:=root.FLeft;
  812. lr:=left;
  813. end;
  814. end;
  815. if root.FLeft<>nil then
  816. begin
  817. { Now the Node pointing to root must point to the left
  818. subtree of root. The right subtree of root must be
  819. connected to the right bottom of the left subtree.}
  820. if lr=left then
  821. oldroot.FLeft:=root.FLeft
  822. else
  823. oldroot.FRight:=root.FLeft;
  824. if root.FRight<>nil then
  825. insert_right_bottom(root.FLeft,root.FRight);
  826. end
  827. else
  828. begin
  829. { There is no left subtree. So we can just replace the Node to
  830. delete with the right subtree.}
  831. if lr=left then
  832. oldroot.FLeft:=root.FRight
  833. else
  834. oldroot.FRight:=root.FRight;
  835. end;
  836. delete_from_tree:=root;
  837. end;
  838. begin
  839. SpeedValue:=GetSpeedValue(s);
  840. n:=FRoot;
  841. if assigned(FHashArray) then
  842. begin
  843. { First, check if the Node to delete directly located under
  844. the hasharray.}
  845. p:=SpeedValue mod hasharraysize;
  846. n:=FHashArray^[p];
  847. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  848. (n.FName^=s) then
  849. begin
  850. { The Node to delete is directly located under the
  851. hasharray. Make the hasharray point to the left
  852. subtree of the Node and place the right subtree on
  853. the right-bottom of the left subtree.}
  854. if n.FLeft<>nil then
  855. begin
  856. FHashArray^[p]:=n.FLeft;
  857. if n.FRight<>nil then
  858. insert_right_bottom(n.FLeft,n.FRight);
  859. end
  860. else
  861. FHashArray^[p]:=n.FRight;
  862. delete:=n;
  863. exit;
  864. end;
  865. end
  866. else
  867. begin
  868. { First check if the Node to delete is the root.}
  869. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  870. (n.FName^=s) then
  871. begin
  872. if n.FLeft<>nil then
  873. begin
  874. FRoot:=n.FLeft;
  875. if n.FRight<>nil then
  876. insert_right_bottom(n.FLeft,n.FRight);
  877. end
  878. else
  879. FRoot:=n.FRight;
  880. delete:=n;
  881. exit;
  882. end;
  883. end;
  884. delete:=delete_from_tree(n);
  885. end;
  886. function Tdictionary.empty:boolean;
  887. var
  888. w : integer;
  889. begin
  890. if assigned(FHashArray) then
  891. begin
  892. empty:=false;
  893. for w:=low(FHashArray^) to high(FHashArray^) do
  894. if assigned(FHashArray^[w]) then
  895. exit;
  896. empty:=true;
  897. end
  898. else
  899. empty:=(FRoot=nil);
  900. end;
  901. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
  902. procedure a(p:TNamedIndexItem;arg:pointer);
  903. begin
  904. proc2call(p,arg);
  905. if assigned(p.FLeft) then
  906. a(p.FLeft,arg);
  907. if assigned(p.FRight) then
  908. a(p.FRight,arg);
  909. end;
  910. var
  911. i : integer;
  912. begin
  913. if assigned(FHashArray) then
  914. begin
  915. for i:=low(FHashArray^) to high(FHashArray^) do
  916. if assigned(FHashArray^[i]) then
  917. a(FHashArray^[i],arg);
  918. end
  919. else
  920. if assigned(FRoot) then
  921. a(FRoot,arg);
  922. end;
  923. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  924. procedure a(p:TNamedIndexItem;arg:pointer);
  925. begin
  926. proc2call(p,arg);
  927. if assigned(p.FLeft) then
  928. a(p.FLeft,arg);
  929. if assigned(p.FRight) then
  930. a(p.FRight,arg);
  931. end;
  932. var
  933. i : integer;
  934. begin
  935. if assigned(FHashArray) then
  936. begin
  937. for i:=low(FHashArray^) to high(FHashArray^) do
  938. if assigned(FHashArray^[i]) then
  939. a(FHashArray^[i],arg);
  940. end
  941. else
  942. if assigned(FRoot) then
  943. a(FRoot,arg);
  944. end;
  945. function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
  946. var
  947. hp : TNamedIndexItem;
  948. begin
  949. hp:=nil;
  950. Replace:=false;
  951. newobj.FSpeedValue:=GetSpeedValue(newobj.FName^);
  952. { must be the same name and hash }
  953. if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
  954. (oldobj.FName^<>newobj.FName^) then
  955. exit;
  956. { copy tree info }
  957. newobj.FLeft:=oldobj.FLeft;
  958. newobj.FRight:=oldobj.FRight;
  959. { update treeroot }
  960. if assigned(FHashArray) then
  961. begin
  962. hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
  963. if hp=oldobj then
  964. begin
  965. FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
  966. hp:=nil;
  967. end;
  968. end
  969. else
  970. begin
  971. hp:=FRoot;
  972. if hp=oldobj then
  973. begin
  974. FRoot:=newobj;
  975. hp:=nil;
  976. end;
  977. end;
  978. { update parent entry }
  979. while assigned(hp) do
  980. begin
  981. { is the node to replace the left or right, then
  982. update this node and stop }
  983. if hp.FLeft=oldobj then
  984. begin
  985. hp.FLeft:=newobj;
  986. break;
  987. end;
  988. if hp.FRight=oldobj then
  989. begin
  990. hp.FRight:=newobj;
  991. break;
  992. end;
  993. { First check SpeedValue, to allow a fast insert }
  994. if hp.SpeedValue>oldobj.SpeedValue then
  995. hp:=hp.FRight
  996. else
  997. if hp.SpeedValue<oldobj.SpeedValue then
  998. hp:=hp.FLeft
  999. else
  1000. begin
  1001. if (hp.FName^=oldobj.FName^) then
  1002. begin
  1003. { this can never happend, return error }
  1004. exit;
  1005. end
  1006. else
  1007. if oldobj.FName^>hp.FName^ then
  1008. hp:=hp.FLeft
  1009. else
  1010. hp:=hp.FRight;
  1011. end;
  1012. end;
  1013. Replace:=true;
  1014. end;
  1015. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  1016. begin
  1017. obj.FSpeedValue:=GetSpeedValue(obj.FName^);
  1018. if assigned(FHashArray) then
  1019. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  1020. else
  1021. insert:=insertNode(obj,FRoot);
  1022. end;
  1023. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  1024. begin
  1025. if currNode=nil then
  1026. begin
  1027. currNode:=NewNode;
  1028. insertNode:=NewNode;
  1029. end
  1030. { First check SpeedValue, to allow a fast insert }
  1031. else
  1032. if currNode.SpeedValue>NewNode.SpeedValue then
  1033. insertNode:=insertNode(NewNode,currNode.FRight)
  1034. else
  1035. if currNode.SpeedValue<NewNode.SpeedValue then
  1036. insertNode:=insertNode(NewNode,currNode.FLeft)
  1037. else
  1038. begin
  1039. if currNode.FName^>NewNode.FName^ then
  1040. insertNode:=insertNode(NewNode,currNode.FRight)
  1041. else
  1042. if currNode.FName^<NewNode.FName^ then
  1043. insertNode:=insertNode(NewNode,currNode.FLeft)
  1044. else
  1045. begin
  1046. if (delete_doubles) and
  1047. assigned(currNode) then
  1048. begin
  1049. NewNode.FLeft:=currNode.FLeft;
  1050. NewNode.FRight:=currNode.FRight;
  1051. if delete_doubles then
  1052. begin
  1053. currnode.FLeft:=nil;
  1054. currnode.FRight:=nil;
  1055. currnode.free;
  1056. end;
  1057. currNode:=NewNode;
  1058. insertNode:=NewNode;
  1059. end
  1060. else
  1061. insertNode:=currNode;
  1062. end;
  1063. end;
  1064. end;
  1065. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  1066. begin
  1067. if assigned(currtree) then
  1068. begin
  1069. inserttree(currtree.FLeft,currroot);
  1070. inserttree(currtree.FRight,currroot);
  1071. currtree.FRight:=nil;
  1072. currtree.FLeft:=nil;
  1073. insertNode(currtree,currroot);
  1074. end;
  1075. end;
  1076. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  1077. var
  1078. spdval : cardinal;
  1079. lasthp,
  1080. hp,hp2,hp3 : TNamedIndexItem;
  1081. begin
  1082. spdval:=GetSpeedValue(olds);
  1083. if assigned(FHashArray) then
  1084. hp:=FHashArray^[spdval mod hasharraysize]
  1085. else
  1086. hp:=FRoot;
  1087. lasthp:=nil;
  1088. while assigned(hp) do
  1089. begin
  1090. if spdval>hp.SpeedValue then
  1091. begin
  1092. lasthp:=hp;
  1093. hp:=hp.FLeft
  1094. end
  1095. else
  1096. if spdval<hp.SpeedValue then
  1097. begin
  1098. lasthp:=hp;
  1099. hp:=hp.FRight
  1100. end
  1101. else
  1102. begin
  1103. if (hp.FName^=olds) then
  1104. begin
  1105. { Get in hp2 the replacer for the root or hasharr }
  1106. hp2:=hp.FLeft;
  1107. hp3:=hp.FRight;
  1108. if not assigned(hp2) then
  1109. begin
  1110. hp2:=hp.FRight;
  1111. hp3:=hp.FLeft;
  1112. end;
  1113. { remove entry from the tree }
  1114. if assigned(lasthp) then
  1115. begin
  1116. if lasthp.FLeft=hp then
  1117. lasthp.FLeft:=hp2
  1118. else
  1119. lasthp.FRight:=hp2;
  1120. end
  1121. else
  1122. begin
  1123. if assigned(FHashArray) then
  1124. FHashArray^[spdval mod hasharraysize]:=hp2
  1125. else
  1126. FRoot:=hp2;
  1127. end;
  1128. { reinsert the hp3 in the tree from hp2 }
  1129. inserttree(hp3,hp2);
  1130. { reset Node with New values }
  1131. hp.FLeft:=nil;
  1132. hp.FRight:=nil;
  1133. stringdispose(hp.FName);
  1134. hp.FName:=stringdup(newS);
  1135. hp.FSpeedValue:=GetSpeedValue(newS);
  1136. { reinsert }
  1137. if assigned(FHashArray) then
  1138. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  1139. else
  1140. rename:=insertNode(hp,FRoot);
  1141. exit;
  1142. end
  1143. else
  1144. if olds>hp.FName^ then
  1145. begin
  1146. lasthp:=hp;
  1147. hp:=hp.FLeft
  1148. end
  1149. else
  1150. begin
  1151. lasthp:=hp;
  1152. hp:=hp.FRight;
  1153. end;
  1154. end;
  1155. end;
  1156. result := nil;
  1157. end;
  1158. function Tdictionary.search(const s:string):TNamedIndexItem;
  1159. begin
  1160. search:=speedsearch(s,GetSpeedValue(s));
  1161. end;
  1162. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  1163. var
  1164. NewNode:TNamedIndexItem;
  1165. begin
  1166. if assigned(FHashArray) then
  1167. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  1168. else
  1169. NewNode:=FRoot;
  1170. while assigned(NewNode) do
  1171. begin
  1172. if SpeedValue>NewNode.SpeedValue then
  1173. NewNode:=NewNode.FLeft
  1174. else
  1175. if SpeedValue<NewNode.SpeedValue then
  1176. NewNode:=NewNode.FRight
  1177. else
  1178. begin
  1179. if (NewNode.FName^=s) then
  1180. begin
  1181. speedsearch:=NewNode;
  1182. exit;
  1183. end
  1184. else
  1185. if s>NewNode.FName^ then
  1186. NewNode:=NewNode.FLeft
  1187. else
  1188. NewNode:=NewNode.FRight;
  1189. end;
  1190. end;
  1191. speedsearch:=nil;
  1192. end;
  1193. {****************************************************************************
  1194. tsingleList
  1195. ****************************************************************************}
  1196. constructor tsingleList.create;
  1197. begin
  1198. First:=nil;
  1199. last:=nil;
  1200. end;
  1201. procedure tsingleList.reset;
  1202. begin
  1203. First:=nil;
  1204. last:=nil;
  1205. end;
  1206. procedure tsingleList.clear;
  1207. var
  1208. hp,hp2 : TNamedIndexItem;
  1209. begin
  1210. hp:=First;
  1211. while assigned(hp) do
  1212. begin
  1213. hp2:=hp;
  1214. hp:=hp.FListNext;
  1215. hp2.free;
  1216. end;
  1217. First:=nil;
  1218. last:=nil;
  1219. end;
  1220. procedure tsingleList.insert(p:TNamedIndexItem);
  1221. begin
  1222. if not assigned(First) then
  1223. First:=p
  1224. else
  1225. last.FListNext:=p;
  1226. last:=p;
  1227. p.FListNext:=nil;
  1228. end;
  1229. {****************************************************************************
  1230. tindexarray
  1231. ****************************************************************************}
  1232. constructor tindexarray.create(Agrowsize:integer);
  1233. begin
  1234. growsize:=Agrowsize;
  1235. size:=0;
  1236. count:=0;
  1237. data:=nil;
  1238. First:=nil;
  1239. noclear:=false;
  1240. end;
  1241. destructor tindexarray.destroy;
  1242. begin
  1243. if assigned(data) then
  1244. begin
  1245. if not noclear then
  1246. clear;
  1247. freemem(data);
  1248. data:=nil;
  1249. end;
  1250. end;
  1251. function tindexarray.search(nr:integer):TNamedIndexItem;
  1252. begin
  1253. if nr<=count then
  1254. search:=data^[nr]
  1255. else
  1256. search:=nil;
  1257. end;
  1258. procedure tindexarray.clear;
  1259. var
  1260. i : integer;
  1261. begin
  1262. for i:=1 to count do
  1263. if assigned(data^[i]) then
  1264. begin
  1265. data^[i].free;
  1266. data^[i]:=nil;
  1267. end;
  1268. count:=0;
  1269. First:=nil;
  1270. end;
  1271. procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
  1272. var
  1273. i : integer;
  1274. begin
  1275. for i:=1 to count do
  1276. if assigned(data^[i]) then
  1277. proc2call(data^[i],arg);
  1278. end;
  1279. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  1280. var
  1281. i : integer;
  1282. begin
  1283. for i:=1 to count do
  1284. if assigned(data^[i]) then
  1285. proc2call(data^[i],arg);
  1286. end;
  1287. procedure tindexarray.grow(gsize:integer);
  1288. var
  1289. osize : integer;
  1290. begin
  1291. osize:=size;
  1292. inc(size,gsize);
  1293. reallocmem(data,size*4);
  1294. fillchar(data^[osize+1],gsize*4,0);
  1295. end;
  1296. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  1297. var
  1298. i : integer;
  1299. begin
  1300. i:=p.Findexnr;
  1301. { update counter }
  1302. if i=count then
  1303. dec(count);
  1304. { update Linked List }
  1305. while (i>0) do
  1306. begin
  1307. dec(i);
  1308. if (i>0) and assigned(data^[i]) then
  1309. begin
  1310. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  1311. break;
  1312. end;
  1313. end;
  1314. if i=0 then
  1315. First:=p.FindexNext;
  1316. data^[p.FIndexnr]:=nil;
  1317. { clear entry }
  1318. p.FIndexnr:=-1;
  1319. p.FIndexNext:=nil;
  1320. end;
  1321. procedure tindexarray.delete(var p:TNamedIndexItem);
  1322. begin
  1323. deleteindex(p);
  1324. p.free;
  1325. p:=nil;
  1326. end;
  1327. procedure tindexarray.insert(p:TNamedIndexItem);
  1328. var
  1329. i : integer;
  1330. begin
  1331. if p.FIndexnr=-1 then
  1332. begin
  1333. inc(count);
  1334. p.FIndexnr:=count;
  1335. end;
  1336. if p.FIndexnr>count then
  1337. count:=p.FIndexnr;
  1338. if count>size then
  1339. grow(((count div growsize)+1)*growsize);
  1340. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  1341. data^[p.FIndexnr]:=p;
  1342. { update Linked List backward }
  1343. i:=p.FIndexnr;
  1344. while (i>0) do
  1345. begin
  1346. dec(i);
  1347. if (i>0) and assigned(data^[i]) then
  1348. begin
  1349. data^[i].FIndexNext:=p;
  1350. break;
  1351. end;
  1352. end;
  1353. if i=0 then
  1354. First:=p;
  1355. { update Linked List forward }
  1356. i:=p.FIndexnr;
  1357. while (i<=count) do
  1358. begin
  1359. inc(i);
  1360. if (i<=count) and assigned(data^[i]) then
  1361. begin
  1362. p.FIndexNext:=data^[i];
  1363. exit;
  1364. end;
  1365. end;
  1366. if i>count then
  1367. p.FIndexNext:=nil;
  1368. end;
  1369. procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
  1370. var
  1371. i : integer;
  1372. begin
  1373. newp.FIndexnr:=oldp.FIndexnr;
  1374. newp.FIndexNext:=oldp.FIndexNext;
  1375. data^[newp.FIndexnr]:=newp;
  1376. { update Linked List backward }
  1377. i:=newp.FIndexnr;
  1378. while (i>0) do
  1379. begin
  1380. dec(i);
  1381. if (i>0) and assigned(data^[i]) then
  1382. begin
  1383. data^[i].FIndexNext:=newp;
  1384. break;
  1385. end;
  1386. end;
  1387. end;
  1388. {****************************************************************************
  1389. tdynamicarray
  1390. ****************************************************************************}
  1391. constructor tdynamicarray.create(Ablocksize:integer);
  1392. begin
  1393. FPosn:=0;
  1394. FPosnblock:=nil;
  1395. FFirstblock:=nil;
  1396. FLastblock:=nil;
  1397. Fblocksize:=Ablocksize;
  1398. grow;
  1399. end;
  1400. destructor tdynamicarray.destroy;
  1401. var
  1402. hp : pdynamicblock;
  1403. begin
  1404. while assigned(FFirstblock) do
  1405. begin
  1406. hp:=FFirstblock;
  1407. FFirstblock:=FFirstblock^.Next;
  1408. freemem(hp,blocksize+dynamicblockbasesize);
  1409. end;
  1410. end;
  1411. function tdynamicarray.size:integer;
  1412. begin
  1413. if assigned(FLastblock) then
  1414. size:=FLastblock^.pos+FLastblock^.used
  1415. else
  1416. size:=0;
  1417. end;
  1418. procedure tdynamicarray.grow;
  1419. var
  1420. nblock : pdynamicblock;
  1421. begin
  1422. Getmem(nblock,blocksize+dynamicblockbasesize);
  1423. if not assigned(FFirstblock) then
  1424. begin
  1425. FFirstblock:=nblock;
  1426. FPosnblock:=nblock;
  1427. nblock^.pos:=0;
  1428. end
  1429. else
  1430. begin
  1431. FLastblock^.Next:=nblock;
  1432. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1433. end;
  1434. nblock^.used:=0;
  1435. nblock^.Next:=nil;
  1436. fillchar(nblock^.data,blocksize,0);
  1437. FLastblock:=nblock;
  1438. end;
  1439. procedure tdynamicarray.align(i:integer);
  1440. var
  1441. j : integer;
  1442. begin
  1443. j:=(FPosn mod i);
  1444. if j<>0 then
  1445. begin
  1446. j:=i-j;
  1447. if FPosnblock^.used+j>blocksize then
  1448. begin
  1449. dec(j,blocksize-FPosnblock^.used);
  1450. FPosnblock^.used:=blocksize;
  1451. grow;
  1452. FPosnblock:=FLastblock;
  1453. end;
  1454. inc(FPosnblock^.used,j);
  1455. inc(FPosn,j);
  1456. end;
  1457. end;
  1458. procedure tdynamicarray.seek(i:integer);
  1459. begin
  1460. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  1461. begin
  1462. { set FPosnblock correct if the size is bigger then
  1463. the current block }
  1464. if FPosnblock^.pos>i then
  1465. FPosnblock:=FFirstblock;
  1466. while assigned(FPosnblock) do
  1467. begin
  1468. if FPosnblock^.pos+blocksize>i then
  1469. break;
  1470. FPosnblock:=FPosnblock^.Next;
  1471. end;
  1472. { not found ? then increase blocks }
  1473. if not assigned(FPosnblock) then
  1474. begin
  1475. { the current FLastblock is now also fully used }
  1476. FLastblock^.used:=blocksize;
  1477. repeat
  1478. grow;
  1479. FPosnblock:=FLastblock;
  1480. until FPosnblock^.pos+blocksize>=i;
  1481. end;
  1482. end;
  1483. FPosn:=i;
  1484. if FPosn mod blocksize>FPosnblock^.used then
  1485. FPosnblock^.used:=FPosn mod blocksize;
  1486. end;
  1487. procedure tdynamicarray.write(const d;len:integer);
  1488. var
  1489. p : pchar;
  1490. i,j : integer;
  1491. begin
  1492. p:=pchar(@d);
  1493. while (len>0) do
  1494. begin
  1495. i:=FPosn mod blocksize;
  1496. if i+len>=blocksize then
  1497. begin
  1498. j:=blocksize-i;
  1499. move(p^,FPosnblock^.data[i],j);
  1500. inc(p,j);
  1501. inc(FPosn,j);
  1502. dec(len,j);
  1503. FPosnblock^.used:=blocksize;
  1504. if assigned(FPosnblock^.Next) then
  1505. FPosnblock:=FPosnblock^.Next
  1506. else
  1507. begin
  1508. grow;
  1509. FPosnblock:=FLastblock;
  1510. end;
  1511. end
  1512. else
  1513. begin
  1514. move(p^,FPosnblock^.data[i],len);
  1515. inc(p,len);
  1516. inc(FPosn,len);
  1517. i:=FPosn mod blocksize;
  1518. if i>FPosnblock^.used then
  1519. FPosnblock^.used:=i;
  1520. len:=0;
  1521. end;
  1522. end;
  1523. end;
  1524. procedure tdynamicarray.writestr(const s:string);
  1525. begin
  1526. write(s[1],length(s));
  1527. end;
  1528. function tdynamicarray.read(var d;len:integer):integer;
  1529. var
  1530. p : pchar;
  1531. i,j,res : integer;
  1532. begin
  1533. res:=0;
  1534. p:=pchar(@d);
  1535. while (len>0) do
  1536. begin
  1537. i:=FPosn mod blocksize;
  1538. if i+len>=FPosnblock^.used then
  1539. begin
  1540. j:=FPosnblock^.used-i;
  1541. move(FPosnblock^.data[i],p^,j);
  1542. inc(p,j);
  1543. inc(FPosn,j);
  1544. inc(res,j);
  1545. dec(len,j);
  1546. if assigned(FPosnblock^.Next) then
  1547. FPosnblock:=FPosnblock^.Next
  1548. else
  1549. break;
  1550. end
  1551. else
  1552. begin
  1553. move(FPosnblock^.data[i],p^,len);
  1554. inc(p,len);
  1555. inc(FPosn,len);
  1556. inc(res,len);
  1557. len:=0;
  1558. end;
  1559. end;
  1560. read:=res;
  1561. end;
  1562. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  1563. var
  1564. i,left : integer;
  1565. begin
  1566. if maxlen=-1 then
  1567. maxlen:=maxlongint;
  1568. repeat
  1569. left:=blocksize-FPosnblock^.used;
  1570. if left>maxlen then
  1571. left:=maxlen;
  1572. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  1573. dec(maxlen,i);
  1574. inc(FPosnblock^.used,i);
  1575. if FPosnblock^.used=blocksize then
  1576. begin
  1577. if assigned(FPosnblock^.Next) then
  1578. FPosnblock:=FPosnblock^.Next
  1579. else
  1580. begin
  1581. grow;
  1582. FPosnblock:=FLastblock;
  1583. end;
  1584. end;
  1585. until (i<left) or (maxlen=0);
  1586. end;
  1587. procedure tdynamicarray.writestream(f:TCStream);
  1588. var
  1589. hp : pdynamicblock;
  1590. begin
  1591. hp:=FFirstblock;
  1592. while assigned(hp) do
  1593. begin
  1594. f.Write(hp^.data,hp^.used);
  1595. hp:=hp^.Next;
  1596. end;
  1597. end;
  1598. end.
  1599. {
  1600. $Log$
  1601. Revision 1.21 2002-11-24 18:18:39 carl
  1602. - remove some unused defines
  1603. Revision 1.20 2002/10/05 12:43:23 carl
  1604. * fixes for Delphi 6 compilation
  1605. (warning : Some features do not work under Delphi)
  1606. Revision 1.19 2002/09/09 17:34:14 peter
  1607. * tdicationary.replace added to replace and item in a dictionary. This
  1608. is only allowed for the same name
  1609. * varsyms are inserted in symtable before the types are parsed. This
  1610. fixes the long standing "var longint : longint" bug
  1611. - consume_idlist and idstringlist removed. The loops are inserted
  1612. at the callers place and uses the symtable for duplicate id checking
  1613. Revision 1.18 2002/09/05 19:29:42 peter
  1614. * memdebug enhancements
  1615. Revision 1.17 2002/08/11 13:24:11 peter
  1616. * saving of asmsymbols in ppu supported
  1617. * asmsymbollist global is removed and moved into a new class
  1618. tasmlibrarydata that will hold the info of a .a file which
  1619. corresponds with a single module. Added librarydata to tmodule
  1620. to keep the library info stored for the module. In the future the
  1621. objectfiles will also be stored to the tasmlibrarydata class
  1622. * all getlabel/newasmsymbol and friends are moved to the new class
  1623. Revision 1.16 2002/08/09 19:08:53 carl
  1624. + fix incorrect comment in insertlistcopy
  1625. Revision 1.15 2002/07/01 18:46:21 peter
  1626. * internal linker
  1627. * reorganized aasm layer
  1628. Revision 1.14 2002/06/17 13:56:14 jonas
  1629. * tdictionary.rename() returns nil if the original object wasn't found
  1630. (reported by Sergey Korshunoff <[email protected]>)
  1631. Revision 1.13 2002/05/18 13:34:05 peter
  1632. * readded missing revisions
  1633. Revision 1.12 2002/05/16 19:46:35 carl
  1634. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1635. + try to fix temp allocation (still in ifdef)
  1636. + generic constructor calls
  1637. + start of tassembler / tmodulebase class cleanup
  1638. Revision 1.10 2002/05/12 16:53:04 peter
  1639. * moved entry and exitcode to ncgutil and cgobj
  1640. * foreach gets extra argument for passing local data to the
  1641. iterator function
  1642. * -CR checks also class typecasts at runtime by changing them
  1643. into as
  1644. * fixed compiler to cycle with the -CR option
  1645. * fixed stabs with elf writer, finally the global variables can
  1646. be watched
  1647. * removed a lot of routines from cga unit and replaced them by
  1648. calls to cgobj
  1649. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1650. u32bit then the other is typecasted also to u32bit without giving
  1651. a rangecheck warning/error.
  1652. * fixed pascal calling method with reversing also the high tree in
  1653. the parast, detected by tcalcst3 test
  1654. }