cclasses.pas 47 KB

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