cclasses.pas 46 KB

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