cclasses.pas 47 KB

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