cclasses.pas 50 KB

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