cclasses.pas 46 KB

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