cclasses.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.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 [-hasharray..hasharray] ! }
  125. hasharraysize = 2047;
  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[-hasharraysize..hasharraysize] of TNamedIndexItem;
  157. TnamedIndexCallback = procedure(p:TNamedIndexItem) of object;
  158. TnamedIndexStaticCallback = procedure(p:TNamedIndexItem);
  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);
  177. procedure foreach_static(proc2call:TNamedIndexStaticCallback);
  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);
  202. procedure foreach_static(proc2call : Tnamedindexstaticcallback);
  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. { Speed/Hash value }
  249. Function GetSpeedValue(Const s:String):cardinal;
  250. implementation
  251. {*****************************************************************************
  252. GetSpeedValue
  253. *****************************************************************************}
  254. {$ifdef ver1_0}
  255. {$R-}
  256. {$endif}
  257. var
  258. Crc32Tbl : array[0..255] of cardinal;
  259. procedure MakeCRC32Tbl;
  260. var
  261. crc : cardinal;
  262. i,n : integer;
  263. begin
  264. for i:=0 to 255 do
  265. begin
  266. crc:=i;
  267. for n:=1 to 8 do
  268. if odd(longint(crc)) then
  269. crc:=cardinal(crc shr 1) xor cardinal($edb88320)
  270. else
  271. crc:=cardinal(crc shr 1);
  272. Crc32Tbl[i]:=crc;
  273. end;
  274. end;
  275. Function GetSpeedValue(Const s:String):cardinal;
  276. var
  277. i : integer;
  278. InitCrc : cardinal;
  279. begin
  280. if Crc32Tbl[1]=0 then
  281. MakeCrc32Tbl;
  282. InitCrc:=cardinal($ffffffff);
  283. for i:=1 to Length(s) do
  284. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  285. GetSpeedValue:=InitCrc;
  286. end;
  287. {*****************************************************************************
  288. Memory debug
  289. *****************************************************************************}
  290. constructor tmemdebug.create(const s:string);
  291. begin
  292. infostr:=s;
  293. {$ifdef Delphi}
  294. startmem:=0;
  295. {$else}
  296. startmem:=memavail;
  297. {$endif Delphi}
  298. end;
  299. destructor tmemdebug.destroy;
  300. begin
  301. show;
  302. end;
  303. procedure tmemdebug.show;
  304. {$ifndef Delphi}
  305. var
  306. l : integer;
  307. {$endif}
  308. begin
  309. {$ifndef Delphi}
  310. write('memory [',infostr,'] ');
  311. l:=memavail;
  312. if l>startmem then
  313. writeln(l-startmem,' released')
  314. else
  315. writeln(startmem-l,' allocated');
  316. {$endif Delphi}
  317. end;
  318. {*****************************************************************************
  319. Stack
  320. *****************************************************************************}
  321. {$ifdef fixLeaksOnError}
  322. constructor TStack.init;
  323. begin
  324. head := nil;
  325. end;
  326. procedure TStack.push(p: pointer);
  327. var s: PStackItem;
  328. begin
  329. New(s);
  330. s^.data := p;
  331. s^.Next := head;
  332. head := s;
  333. end;
  334. function TStack.pop: pointer;
  335. var s: PStackItem;
  336. begin
  337. pop := top;
  338. if assigned(head) then
  339. begin
  340. s := head^.Next;
  341. dispose(head);
  342. head := s;
  343. end
  344. end;
  345. function TStack.top: pointer;
  346. begin
  347. if not isEmpty then
  348. top := head^.data
  349. else top := NIL;
  350. end;
  351. function TStack.isEmpty: boolean;
  352. begin
  353. isEmpty := head = nil;
  354. end;
  355. destructor TStack.done;
  356. var temp: PStackItem;
  357. begin
  358. while head <> nil do
  359. begin
  360. temp := head^.Next;
  361. dispose(head);
  362. head := temp;
  363. end;
  364. end;
  365. {$endif fixLeaksOnError}
  366. {****************************************************************************
  367. TLinkedListItem
  368. ****************************************************************************}
  369. constructor TLinkedListItem.Create;
  370. begin
  371. Previous:=nil;
  372. Next:=nil;
  373. end;
  374. destructor TLinkedListItem.Destroy;
  375. begin
  376. end;
  377. function TLinkedListItem.GetCopy:TLinkedListItem;
  378. var
  379. p : TLinkedListItem;
  380. l : integer;
  381. begin
  382. p:=TLinkedListItemClass(ClassType).Create;
  383. l:=InstanceSize;
  384. Move(pointer(self)^,pointer(p)^,l);
  385. Result:=p;
  386. end;
  387. {****************************************************************************
  388. TLinkedList
  389. ****************************************************************************}
  390. constructor TLinkedList.Create;
  391. begin
  392. FFirst:=nil;
  393. Flast:=nil;
  394. FCount:=0;
  395. end;
  396. destructor TLinkedList.destroy;
  397. begin
  398. Clear;
  399. end;
  400. function TLinkedList.empty:boolean;
  401. begin
  402. Empty:=(FFirst=nil);
  403. end;
  404. procedure TLinkedList.Insert(Item:TLinkedListItem);
  405. begin
  406. if FFirst=nil then
  407. begin
  408. FLast:=Item;
  409. Item.Previous:=nil;
  410. Item.Next:=nil;
  411. end
  412. else
  413. begin
  414. FFirst.Previous:=Item;
  415. Item.Previous:=nil;
  416. Item.Next:=FFirst;
  417. end;
  418. FFirst:=Item;
  419. inc(FCount);
  420. end;
  421. procedure TLinkedList.Concat(Item:TLinkedListItem);
  422. begin
  423. if FFirst=nil then
  424. begin
  425. FFirst:=Item;
  426. Item.Previous:=nil;
  427. Item.Next:=nil;
  428. end
  429. else
  430. begin
  431. Flast.Next:=Item;
  432. Item.Previous:=Flast;
  433. Item.Next:=nil;
  434. end;
  435. Flast:=Item;
  436. inc(FCount);
  437. end;
  438. procedure TLinkedList.remove(Item:TLinkedListItem);
  439. begin
  440. if Item=nil then
  441. exit;
  442. if (FFirst=Item) and (Flast=Item) then
  443. begin
  444. FFirst:=nil;
  445. Flast:=nil;
  446. end
  447. else if FFirst=Item then
  448. begin
  449. FFirst:=Item.Next;
  450. if assigned(FFirst) then
  451. FFirst.Previous:=nil;
  452. end
  453. else if Flast=Item then
  454. begin
  455. Flast:=Flast.Previous;
  456. if assigned(Flast) then
  457. Flast.Next:=nil;
  458. end
  459. else
  460. begin
  461. Item.Previous.Next:=Item.Next;
  462. Item.Next.Previous:=Item.Previous;
  463. end;
  464. Item.Next:=nil;
  465. Item.Previous:=nil;
  466. dec(FCount);
  467. end;
  468. procedure TLinkedList.clear;
  469. var
  470. NewNode : TLinkedListItem;
  471. begin
  472. NewNode:=FFirst;
  473. while assigned(NewNode) do
  474. begin
  475. FFirst:=NewNode.Next;
  476. NewNode.Free;
  477. NewNode:=FFirst;
  478. end;
  479. FLast:=nil;
  480. FFirst:=nil;
  481. FCount:=0;
  482. end;
  483. function TLinkedList.GetFirst:TLinkedListItem;
  484. begin
  485. if FFirst=nil then
  486. GetFirst:=nil
  487. else
  488. begin
  489. GetFirst:=FFirst;
  490. if FFirst=FLast then
  491. FLast:=nil;
  492. FFirst:=FFirst.Next;
  493. dec(FCount);
  494. end;
  495. end;
  496. function TLinkedList.GetLast:TLinkedListItem;
  497. begin
  498. if FLast=nil then
  499. Getlast:=nil
  500. else
  501. begin
  502. Getlast:=FLast;
  503. if FLast=FFirst then
  504. FFirst:=nil;
  505. FLast:=FLast.Previous;
  506. dec(FCount);
  507. end;
  508. end;
  509. procedure TLinkedList.insertList(p : TLinkedList);
  510. begin
  511. { empty List ? }
  512. if (p.FFirst=nil) then
  513. exit;
  514. p.Flast.Next:=FFirst;
  515. { we have a double Linked List }
  516. if assigned(FFirst) then
  517. FFirst.Previous:=p.Flast;
  518. FFirst:=p.FFirst;
  519. if (FLast=nil) then
  520. Flast:=p.Flast;
  521. { p becomes empty }
  522. p.FFirst:=nil;
  523. p.Flast:=nil;
  524. end;
  525. procedure TLinkedList.concatList(p : TLinkedList);
  526. begin
  527. if (p.FFirst=nil) then
  528. exit;
  529. if FFirst=nil then
  530. FFirst:=p.FFirst
  531. else
  532. begin
  533. FLast.Next:=p.FFirst;
  534. p.FFirst.Previous:=Flast;
  535. end;
  536. Flast:=p.Flast;
  537. { make p empty }
  538. p.Flast:=nil;
  539. p.FFirst:=nil;
  540. end;
  541. procedure TLinkedList.insertListcopy(p : TLinkedList);
  542. var
  543. NewNode,NewNode2 : TLinkedListItem;
  544. begin
  545. NewNode:=p.First;
  546. while assigned(NewNode) do
  547. begin
  548. NewNode2:=NewNode.Getcopy;
  549. if assigned(NewNode2) then
  550. Insert(NewNode2);
  551. NewNode:=NewNode.Next;
  552. end;
  553. end;
  554. procedure TLinkedList.concatListcopy(p : TLinkedList);
  555. var
  556. NewNode,NewNode2 : TLinkedListItem;
  557. begin
  558. NewNode:=p.First;
  559. while assigned(NewNode) do
  560. begin
  561. NewNode2:=NewNode.Getcopy;
  562. if assigned(NewNode2) then
  563. Concat(NewNode2);
  564. NewNode:=NewNode.Next;
  565. end;
  566. end;
  567. {****************************************************************************
  568. TStringListItem
  569. ****************************************************************************}
  570. constructor TStringListItem.Create(const s:string);
  571. begin
  572. inherited Create;
  573. FPStr:=stringdup(s);
  574. end;
  575. destructor TStringListItem.Destroy;
  576. begin
  577. stringdispose(FPStr);
  578. end;
  579. function TStringListItem.Str:string;
  580. begin
  581. Str:=FPStr^;
  582. end;
  583. function TStringListItem.GetCopy:TLinkedListItem;
  584. begin
  585. Result:=(inherited GetCopy);
  586. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  587. end;
  588. {****************************************************************************
  589. TSTRINGList
  590. ****************************************************************************}
  591. constructor tstringList.Create;
  592. begin
  593. inherited Create;
  594. FDoubles:=true;
  595. end;
  596. constructor tstringList.Create_no_double;
  597. begin
  598. inherited Create;
  599. FDoubles:=false;
  600. end;
  601. procedure tstringList.insert(const s : string);
  602. begin
  603. if (s='') or
  604. ((not FDoubles) and (find(s)<>nil)) then
  605. exit;
  606. inherited insert(tstringListItem.create(s));
  607. end;
  608. procedure tstringList.concat(const s : string);
  609. begin
  610. if (s='') or
  611. ((not FDoubles) and (find(s)<>nil)) then
  612. exit;
  613. inherited concat(tstringListItem.create(s));
  614. end;
  615. procedure tstringList.remove(const s : string);
  616. var
  617. p : tstringListItem;
  618. begin
  619. if s='' then
  620. exit;
  621. p:=find(s);
  622. if assigned(p) then
  623. begin
  624. inherited Remove(p);
  625. p.Free;
  626. end;
  627. end;
  628. function tstringList.GetFirst : string;
  629. var
  630. p : tstringListItem;
  631. begin
  632. p:=tstringListItem(inherited GetFirst);
  633. if p=nil then
  634. GetFirst:=''
  635. else
  636. begin
  637. GetFirst:=p.FPStr^;
  638. p.free;
  639. end;
  640. end;
  641. function tstringList.Getlast : string;
  642. var
  643. p : tstringListItem;
  644. begin
  645. p:=tstringListItem(inherited Getlast);
  646. if p=nil then
  647. Getlast:=''
  648. else
  649. begin
  650. Getlast:=p.FPStr^;
  651. p.free;
  652. end;
  653. end;
  654. function tstringList.find(const s:string):TstringListItem;
  655. var
  656. NewNode : tstringListItem;
  657. begin
  658. find:=nil;
  659. if s='' then
  660. exit;
  661. NewNode:=tstringListItem(FFirst);
  662. while assigned(NewNode) do
  663. begin
  664. if NewNode.FPStr^=s then
  665. begin
  666. find:=NewNode;
  667. exit;
  668. end;
  669. NewNode:=tstringListItem(NewNode.Next);
  670. end;
  671. end;
  672. procedure TStringList.InsertItem(item:TStringListItem);
  673. begin
  674. inherited Insert(item);
  675. end;
  676. procedure TStringList.ConcatItem(item:TStringListItem);
  677. begin
  678. inherited Concat(item);
  679. end;
  680. {****************************************************************************
  681. TNamedIndexItem
  682. ****************************************************************************}
  683. constructor TNamedIndexItem.Create;
  684. begin
  685. { index }
  686. Findexnr:=-1;
  687. FindexNext:=nil;
  688. { dictionary }
  689. Fleft:=nil;
  690. Fright:=nil;
  691. FName:=nil;
  692. Fspeedvalue:=cardinal($ffffffff);
  693. { List }
  694. FListNext:=nil;
  695. end;
  696. constructor TNamedIndexItem.Createname(const n:string);
  697. begin
  698. { index }
  699. Findexnr:=-1;
  700. FindexNext:=nil;
  701. { dictionary }
  702. Fleft:=nil;
  703. Fright:=nil;
  704. Fspeedvalue:=cardinal($ffffffff);
  705. FName:=stringdup(n);
  706. { List }
  707. FListNext:=nil;
  708. end;
  709. destructor TNamedIndexItem.destroy;
  710. begin
  711. stringdispose(FName);
  712. end;
  713. procedure TNamedIndexItem.setname(const n:string);
  714. begin
  715. if speedvalue=cardinal($ffffffff) then
  716. begin
  717. if assigned(FName) then
  718. stringdispose(FName);
  719. FName:=stringdup(n);
  720. end;
  721. end;
  722. function TNamedIndexItem.GetName:string;
  723. begin
  724. if assigned(FName) then
  725. Getname:=FName^
  726. else
  727. Getname:='';
  728. end;
  729. {****************************************************************************
  730. TDICTIONARY
  731. ****************************************************************************}
  732. constructor Tdictionary.Create;
  733. begin
  734. FRoot:=nil;
  735. FHashArray:=nil;
  736. noclear:=false;
  737. replace_existing:=false;
  738. delete_doubles:=false;
  739. end;
  740. procedure Tdictionary.usehash;
  741. begin
  742. if not(assigned(FRoot)) and
  743. not(assigned(FHashArray)) then
  744. begin
  745. New(FHashArray);
  746. fillchar(FHashArray^,sizeof(FHashArray^),0);
  747. end;
  748. end;
  749. destructor Tdictionary.destroy;
  750. begin
  751. if not noclear then
  752. clear;
  753. if assigned(FHashArray) then
  754. dispose(FHashArray);
  755. end;
  756. procedure Tdictionary.cleartree(obj:TNamedIndexItem);
  757. begin
  758. if assigned(obj.Fleft) then
  759. cleartree(obj.FLeft);
  760. if assigned(obj.FRight) then
  761. cleartree(obj.FRight);
  762. obj.free;
  763. obj:=nil;
  764. end;
  765. procedure Tdictionary.clear;
  766. var
  767. w : integer;
  768. begin
  769. if assigned(FRoot) then
  770. cleartree(FRoot);
  771. if assigned(FHashArray) then
  772. for w:=-hasharraysize to hasharraysize do
  773. if assigned(FHashArray^[w]) then
  774. cleartree(FHashArray^[w]);
  775. end;
  776. function Tdictionary.delete(const s:string):TNamedIndexItem;
  777. var
  778. p,SpeedValue : cardinal;
  779. n : TNamedIndexItem;
  780. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  781. begin
  782. while root.FRight<>nil do
  783. root:=root.FRight;
  784. root.FRight:=Atree;
  785. end;
  786. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  787. type
  788. leftright=(left,right);
  789. var
  790. lr : leftright;
  791. oldroot : TNamedIndexItem;
  792. begin
  793. oldroot:=nil;
  794. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  795. begin
  796. oldroot:=root;
  797. if SpeedValue<root.SpeedValue then
  798. begin
  799. root:=root.FRight;
  800. lr:=right;
  801. end
  802. else
  803. begin
  804. root:=root.FLeft;
  805. lr:=left;
  806. end;
  807. end;
  808. while (root<>nil) and (root.FName^<>s) do
  809. begin
  810. oldroot:=root;
  811. if s<root.FName^ then
  812. begin
  813. root:=root.FRight;
  814. lr:=right;
  815. end
  816. else
  817. begin
  818. root:=root.FLeft;
  819. lr:=left;
  820. end;
  821. end;
  822. if root.FLeft<>nil then
  823. begin
  824. { Now the Node pointing to root must point to the left
  825. subtree of root. The right subtree of root must be
  826. connected to the right bottom of the left subtree.}
  827. if lr=left then
  828. oldroot.FLeft:=root.FLeft
  829. else
  830. oldroot.FRight:=root.FLeft;
  831. if root.FRight<>nil then
  832. insert_right_bottom(root.FLeft,root.FRight);
  833. end
  834. else
  835. begin
  836. { There is no left subtree. So we can just replace the Node to
  837. delete with the right subtree.}
  838. if lr=left then
  839. oldroot.FLeft:=root.FRight
  840. else
  841. oldroot.FRight:=root.FRight;
  842. end;
  843. delete_from_tree:=root;
  844. end;
  845. begin
  846. SpeedValue:=GetSpeedValue(s);
  847. n:=FRoot;
  848. if assigned(FHashArray) then
  849. begin
  850. { First, check if the Node to delete directly located under
  851. the hasharray.}
  852. p:=SpeedValue mod hasharraysize;
  853. n:=FHashArray^[p];
  854. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  855. (n.FName^=s) then
  856. begin
  857. { The Node to delete is directly located under the
  858. hasharray. Make the hasharray point to the left
  859. subtree of the Node and place the right subtree on
  860. the right-bottom of the left subtree.}
  861. if n.FLeft<>nil then
  862. begin
  863. FHashArray^[p]:=n.FLeft;
  864. if n.FRight<>nil then
  865. insert_right_bottom(n.FLeft,n.FRight);
  866. end
  867. else
  868. FHashArray^[p]:=n.FRight;
  869. delete:=n;
  870. exit;
  871. end;
  872. end
  873. else
  874. begin
  875. { First check if the Node to delete is the root.}
  876. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  877. (n.FName^=s) then
  878. begin
  879. if n.FLeft<>nil then
  880. begin
  881. FRoot:=n.FLeft;
  882. if n.FRight<>nil then
  883. insert_right_bottom(n.FLeft,n.FRight);
  884. end
  885. else
  886. FRoot:=n.FRight;
  887. delete:=n;
  888. exit;
  889. end;
  890. end;
  891. delete:=delete_from_tree(n);
  892. end;
  893. function Tdictionary.empty:boolean;
  894. var
  895. w : integer;
  896. begin
  897. if assigned(FHashArray) then
  898. begin
  899. empty:=false;
  900. for w:=-hasharraysize to hasharraysize do
  901. if assigned(FHashArray^[w]) then
  902. exit;
  903. empty:=true;
  904. end
  905. else
  906. empty:=(FRoot=nil);
  907. end;
  908. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback);
  909. procedure a(p:TNamedIndexItem);
  910. begin
  911. proc2call(p);
  912. if assigned(p.FLeft) then
  913. a(p.FLeft);
  914. if assigned(p.FRight) then
  915. a(p.FRight);
  916. end;
  917. var
  918. i : integer;
  919. begin
  920. if assigned(FHashArray) then
  921. begin
  922. for i:=-hasharraysize to hasharraysize do
  923. if assigned(FHashArray^[i]) then
  924. a(FHashArray^[i]);
  925. end
  926. else
  927. if assigned(FRoot) then
  928. a(FRoot);
  929. end;
  930. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback);
  931. procedure a(p:TNamedIndexItem);
  932. begin
  933. proc2call(p);
  934. if assigned(p.FLeft) then
  935. a(p.FLeft);
  936. if assigned(p.FRight) then
  937. a(p.FRight);
  938. end;
  939. var
  940. i : integer;
  941. begin
  942. if assigned(FHashArray) then
  943. begin
  944. for i:=-hasharraysize to hasharraysize do
  945. if assigned(FHashArray^[i]) then
  946. a(FHashArray^[i]);
  947. end
  948. else
  949. if assigned(FRoot) then
  950. a(FRoot);
  951. end;
  952. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  953. begin
  954. obj.FSpeedValue:=GetSpeedValue(obj.FName^);
  955. if assigned(FHashArray) then
  956. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  957. else
  958. insert:=insertNode(obj,FRoot);
  959. end;
  960. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  961. begin
  962. if currNode=nil then
  963. begin
  964. currNode:=NewNode;
  965. insertNode:=NewNode;
  966. end
  967. { First check SpeedValue, to allow a fast insert }
  968. else
  969. if currNode.SpeedValue>NewNode.SpeedValue then
  970. insertNode:=insertNode(NewNode,currNode.FRight)
  971. else
  972. if currNode.SpeedValue<NewNode.SpeedValue then
  973. insertNode:=insertNode(NewNode,currNode.FLeft)
  974. else
  975. begin
  976. if currNode.FName^>NewNode.FName^ then
  977. insertNode:=insertNode(NewNode,currNode.FRight)
  978. else
  979. if currNode.FName^<NewNode.FName^ then
  980. insertNode:=insertNode(NewNode,currNode.FLeft)
  981. else
  982. begin
  983. if (replace_existing or delete_doubles) and
  984. assigned(currNode) then
  985. begin
  986. NewNode.FLeft:=currNode.FLeft;
  987. NewNode.FRight:=currNode.FRight;
  988. if delete_doubles then
  989. begin
  990. currnode.FLeft:=nil;
  991. currnode.FRight:=nil;
  992. currnode.free;
  993. end;
  994. currNode:=NewNode;
  995. insertNode:=NewNode;
  996. end
  997. else
  998. insertNode:=currNode;
  999. end;
  1000. end;
  1001. end;
  1002. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  1003. begin
  1004. if assigned(currtree) then
  1005. begin
  1006. inserttree(currtree.FLeft,currroot);
  1007. inserttree(currtree.FRight,currroot);
  1008. currtree.FRight:=nil;
  1009. currtree.FLeft:=nil;
  1010. insertNode(currtree,currroot);
  1011. end;
  1012. end;
  1013. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  1014. var
  1015. spdval : cardinal;
  1016. lasthp,
  1017. hp,hp2,hp3 : TNamedIndexItem;
  1018. begin
  1019. spdval:=GetSpeedValue(olds);
  1020. if assigned(FHashArray) then
  1021. hp:=FHashArray^[spdval mod hasharraysize]
  1022. else
  1023. hp:=FRoot;
  1024. lasthp:=nil;
  1025. while assigned(hp) do
  1026. begin
  1027. if spdval>hp.SpeedValue then
  1028. begin
  1029. lasthp:=hp;
  1030. hp:=hp.FLeft
  1031. end
  1032. else
  1033. if spdval<hp.SpeedValue then
  1034. begin
  1035. lasthp:=hp;
  1036. hp:=hp.FRight
  1037. end
  1038. else
  1039. begin
  1040. if (hp.FName^=olds) then
  1041. begin
  1042. { Get in hp2 the replacer for the root or hasharr }
  1043. hp2:=hp.FLeft;
  1044. hp3:=hp.FRight;
  1045. if not assigned(hp2) then
  1046. begin
  1047. hp2:=hp.FRight;
  1048. hp3:=hp.FLeft;
  1049. end;
  1050. { remove entry from the tree }
  1051. if assigned(lasthp) then
  1052. begin
  1053. if lasthp.FLeft=hp then
  1054. lasthp.FLeft:=hp2
  1055. else
  1056. lasthp.FRight:=hp2;
  1057. end
  1058. else
  1059. begin
  1060. if assigned(FHashArray) then
  1061. FHashArray^[spdval mod hasharraysize]:=hp2
  1062. else
  1063. FRoot:=hp2;
  1064. end;
  1065. { reinsert the hp3 in the tree from hp2 }
  1066. inserttree(hp3,hp2);
  1067. { reset Node with New values }
  1068. hp.FLeft:=nil;
  1069. hp.FRight:=nil;
  1070. stringdispose(hp.FName);
  1071. hp.FName:=stringdup(newS);
  1072. hp.FSpeedValue:=GetSpeedValue(newS);
  1073. { reinsert }
  1074. if assigned(FHashArray) then
  1075. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  1076. else
  1077. rename:=insertNode(hp,FRoot);
  1078. exit;
  1079. end
  1080. else
  1081. if olds>hp.FName^ then
  1082. begin
  1083. lasthp:=hp;
  1084. hp:=hp.FLeft
  1085. end
  1086. else
  1087. begin
  1088. lasthp:=hp;
  1089. hp:=hp.FRight;
  1090. end;
  1091. end;
  1092. end;
  1093. end;
  1094. function Tdictionary.search(const s:string):TNamedIndexItem;
  1095. begin
  1096. search:=speedsearch(s,GetSpeedValue(s));
  1097. end;
  1098. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  1099. var
  1100. NewNode:TNamedIndexItem;
  1101. begin
  1102. if assigned(FHashArray) then
  1103. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  1104. else
  1105. NewNode:=FRoot;
  1106. while assigned(NewNode) do
  1107. begin
  1108. if SpeedValue>NewNode.SpeedValue then
  1109. NewNode:=NewNode.FLeft
  1110. else
  1111. if SpeedValue<NewNode.SpeedValue then
  1112. NewNode:=NewNode.FRight
  1113. else
  1114. begin
  1115. if (NewNode.FName^=s) then
  1116. begin
  1117. speedsearch:=NewNode;
  1118. exit;
  1119. end
  1120. else
  1121. if s>NewNode.FName^ then
  1122. NewNode:=NewNode.FLeft
  1123. else
  1124. NewNode:=NewNode.FRight;
  1125. end;
  1126. end;
  1127. speedsearch:=nil;
  1128. end;
  1129. {****************************************************************************
  1130. tsingleList
  1131. ****************************************************************************}
  1132. constructor tsingleList.create;
  1133. begin
  1134. First:=nil;
  1135. last:=nil;
  1136. end;
  1137. procedure tsingleList.reset;
  1138. begin
  1139. First:=nil;
  1140. last:=nil;
  1141. end;
  1142. procedure tsingleList.clear;
  1143. var
  1144. hp,hp2 : TNamedIndexItem;
  1145. begin
  1146. hp:=First;
  1147. while assigned(hp) do
  1148. begin
  1149. hp2:=hp;
  1150. hp:=hp.FListNext;
  1151. hp2.free;
  1152. end;
  1153. First:=nil;
  1154. last:=nil;
  1155. end;
  1156. procedure tsingleList.insert(p:TNamedIndexItem);
  1157. begin
  1158. if not assigned(First) then
  1159. First:=p
  1160. else
  1161. last.FListNext:=p;
  1162. last:=p;
  1163. p.FListNext:=nil;
  1164. end;
  1165. {****************************************************************************
  1166. tindexarray
  1167. ****************************************************************************}
  1168. constructor tindexarray.create(Agrowsize:integer);
  1169. begin
  1170. growsize:=Agrowsize;
  1171. size:=0;
  1172. count:=0;
  1173. data:=nil;
  1174. First:=nil;
  1175. noclear:=false;
  1176. end;
  1177. destructor tindexarray.destroy;
  1178. begin
  1179. if assigned(data) then
  1180. begin
  1181. if not noclear then
  1182. clear;
  1183. freemem(data);
  1184. data:=nil;
  1185. end;
  1186. end;
  1187. function tindexarray.search(nr:integer):TNamedIndexItem;
  1188. begin
  1189. if nr<=count then
  1190. search:=data^[nr]
  1191. else
  1192. search:=nil;
  1193. end;
  1194. procedure tindexarray.clear;
  1195. var
  1196. i : integer;
  1197. begin
  1198. for i:=1 to count do
  1199. if assigned(data^[i]) then
  1200. begin
  1201. data^[i].free;
  1202. data^[i]:=nil;
  1203. end;
  1204. count:=0;
  1205. First:=nil;
  1206. end;
  1207. procedure tindexarray.foreach(proc2call : Tnamedindexcallback);
  1208. var
  1209. i : integer;
  1210. begin
  1211. for i:=1 to count do
  1212. if assigned(data^[i]) then
  1213. proc2call(data^[i]);
  1214. end;
  1215. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback);
  1216. var
  1217. i : integer;
  1218. begin
  1219. for i:=1 to count do
  1220. if assigned(data^[i]) then
  1221. proc2call(data^[i]);
  1222. end;
  1223. procedure tindexarray.grow(gsize:integer);
  1224. var
  1225. osize : integer;
  1226. begin
  1227. osize:=size;
  1228. inc(size,gsize);
  1229. reallocmem(data,size*4);
  1230. fillchar(data^[osize+1],gsize*4,0);
  1231. end;
  1232. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  1233. var
  1234. i : integer;
  1235. begin
  1236. i:=p.Findexnr;
  1237. { update counter }
  1238. if i=count then
  1239. dec(count);
  1240. { update Linked List }
  1241. while (i>0) do
  1242. begin
  1243. dec(i);
  1244. if (i>0) and assigned(data^[i]) then
  1245. begin
  1246. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  1247. break;
  1248. end;
  1249. end;
  1250. if i=0 then
  1251. First:=p.FindexNext;
  1252. data^[p.FIndexnr]:=nil;
  1253. { clear entry }
  1254. p.FIndexnr:=-1;
  1255. p.FIndexNext:=nil;
  1256. end;
  1257. procedure tindexarray.delete(var p:TNamedIndexItem);
  1258. begin
  1259. deleteindex(p);
  1260. p.free;
  1261. p:=nil;
  1262. end;
  1263. procedure tindexarray.insert(p:TNamedIndexItem);
  1264. var
  1265. i : integer;
  1266. begin
  1267. if p.FIndexnr=-1 then
  1268. begin
  1269. inc(count);
  1270. p.FIndexnr:=count;
  1271. end;
  1272. if p.FIndexnr>count then
  1273. count:=p.FIndexnr;
  1274. if count>size then
  1275. grow(((count div growsize)+1)*growsize);
  1276. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  1277. data^[p.FIndexnr]:=p;
  1278. { update Linked List backward }
  1279. i:=p.FIndexnr;
  1280. while (i>0) do
  1281. begin
  1282. dec(i);
  1283. if (i>0) and assigned(data^[i]) then
  1284. begin
  1285. data^[i].FIndexNext:=p;
  1286. break;
  1287. end;
  1288. end;
  1289. if i=0 then
  1290. First:=p;
  1291. { update Linked List forward }
  1292. i:=p.FIndexnr;
  1293. while (i<=count) do
  1294. begin
  1295. inc(i);
  1296. if (i<=count) and assigned(data^[i]) then
  1297. begin
  1298. p.FIndexNext:=data^[i];
  1299. exit;
  1300. end;
  1301. end;
  1302. if i>count then
  1303. p.FIndexNext:=nil;
  1304. end;
  1305. {****************************************************************************
  1306. tdynamicarray
  1307. ****************************************************************************}
  1308. constructor tdynamicarray.create(Ablocksize:integer);
  1309. begin
  1310. FPosn:=0;
  1311. FPosnblock:=nil;
  1312. FFirstblock:=nil;
  1313. FLastblock:=nil;
  1314. Fblocksize:=Ablocksize;
  1315. grow;
  1316. end;
  1317. destructor tdynamicarray.destroy;
  1318. var
  1319. hp : pdynamicblock;
  1320. begin
  1321. while assigned(FFirstblock) do
  1322. begin
  1323. hp:=FFirstblock;
  1324. FFirstblock:=FFirstblock^.Next;
  1325. freemem(hp,blocksize+dynamicblockbasesize);
  1326. end;
  1327. end;
  1328. function tdynamicarray.size:integer;
  1329. begin
  1330. if assigned(FLastblock) then
  1331. size:=FLastblock^.pos+FLastblock^.used
  1332. else
  1333. size:=0;
  1334. end;
  1335. procedure tdynamicarray.grow;
  1336. var
  1337. nblock : pdynamicblock;
  1338. begin
  1339. Getmem(nblock,blocksize+dynamicblockbasesize);
  1340. if not assigned(FFirstblock) then
  1341. begin
  1342. FFirstblock:=nblock;
  1343. FPosnblock:=nblock;
  1344. nblock^.pos:=0;
  1345. end
  1346. else
  1347. begin
  1348. FLastblock^.Next:=nblock;
  1349. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1350. end;
  1351. nblock^.used:=0;
  1352. nblock^.Next:=nil;
  1353. fillchar(nblock^.data,blocksize,0);
  1354. FLastblock:=nblock;
  1355. end;
  1356. procedure tdynamicarray.align(i:integer);
  1357. var
  1358. j : integer;
  1359. begin
  1360. j:=(FPosn mod i);
  1361. if j<>0 then
  1362. begin
  1363. j:=i-j;
  1364. if FPosnblock^.used+j>blocksize then
  1365. begin
  1366. dec(j,blocksize-FPosnblock^.used);
  1367. FPosnblock^.used:=blocksize;
  1368. grow;
  1369. FPosnblock:=FLastblock;
  1370. end;
  1371. inc(FPosnblock^.used,j);
  1372. inc(FPosn,j);
  1373. end;
  1374. end;
  1375. procedure tdynamicarray.seek(i:integer);
  1376. begin
  1377. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  1378. begin
  1379. { set FPosnblock correct if the size is bigger then
  1380. the current block }
  1381. if FPosnblock^.pos>i then
  1382. FPosnblock:=FFirstblock;
  1383. while assigned(FPosnblock) do
  1384. begin
  1385. if FPosnblock^.pos+blocksize>i then
  1386. break;
  1387. FPosnblock:=FPosnblock^.Next;
  1388. end;
  1389. { not found ? then increase blocks }
  1390. if not assigned(FPosnblock) then
  1391. begin
  1392. { the current FLastblock is now also fully used }
  1393. FLastblock^.used:=blocksize;
  1394. repeat
  1395. grow;
  1396. FPosnblock:=FLastblock;
  1397. until FPosnblock^.pos+blocksize>=i;
  1398. end;
  1399. end;
  1400. FPosn:=i;
  1401. if FPosn mod blocksize>FPosnblock^.used then
  1402. FPosnblock^.used:=FPosn mod blocksize;
  1403. end;
  1404. procedure tdynamicarray.write(const d;len:integer);
  1405. var
  1406. p : pchar;
  1407. i,j : integer;
  1408. begin
  1409. p:=pchar(@d);
  1410. while (len>0) do
  1411. begin
  1412. i:=FPosn mod blocksize;
  1413. if i+len>=blocksize then
  1414. begin
  1415. j:=blocksize-i;
  1416. move(p^,FPosnblock^.data[i],j);
  1417. inc(p,j);
  1418. inc(FPosn,j);
  1419. dec(len,j);
  1420. FPosnblock^.used:=blocksize;
  1421. if assigned(FPosnblock^.Next) then
  1422. FPosnblock:=FPosnblock^.Next
  1423. else
  1424. begin
  1425. grow;
  1426. FPosnblock:=FLastblock;
  1427. end;
  1428. end
  1429. else
  1430. begin
  1431. move(p^,FPosnblock^.data[i],len);
  1432. inc(p,len);
  1433. inc(FPosn,len);
  1434. i:=FPosn mod blocksize;
  1435. if i>FPosnblock^.used then
  1436. FPosnblock^.used:=i;
  1437. len:=0;
  1438. end;
  1439. end;
  1440. end;
  1441. procedure tdynamicarray.writestr(const s:string);
  1442. begin
  1443. write(s[1],length(s));
  1444. end;
  1445. function tdynamicarray.read(var d;len:integer):integer;
  1446. var
  1447. p : pchar;
  1448. i,j,res : integer;
  1449. begin
  1450. res:=0;
  1451. p:=pchar(@d);
  1452. while (len>0) do
  1453. begin
  1454. i:=FPosn mod blocksize;
  1455. if i+len>=FPosnblock^.used then
  1456. begin
  1457. j:=FPosnblock^.used-i;
  1458. move(FPosnblock^.data[i],p^,j);
  1459. inc(p,j);
  1460. inc(FPosn,j);
  1461. inc(res,j);
  1462. dec(len,j);
  1463. if assigned(FPosnblock^.Next) then
  1464. FPosnblock:=FPosnblock^.Next
  1465. else
  1466. break;
  1467. end
  1468. else
  1469. begin
  1470. move(FPosnblock^.data[i],p^,len);
  1471. inc(p,len);
  1472. inc(FPosn,len);
  1473. inc(res,len);
  1474. len:=0;
  1475. end;
  1476. end;
  1477. read:=res;
  1478. end;
  1479. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  1480. var
  1481. i,left : integer;
  1482. begin
  1483. if maxlen=-1 then
  1484. maxlen:=maxlongint;
  1485. repeat
  1486. left:=blocksize-FPosnblock^.used;
  1487. if left>maxlen then
  1488. left:=maxlen;
  1489. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  1490. dec(maxlen,i);
  1491. inc(FPosnblock^.used,i);
  1492. if FPosnblock^.used=blocksize then
  1493. begin
  1494. if assigned(FPosnblock^.Next) then
  1495. FPosnblock:=FPosnblock^.Next
  1496. else
  1497. begin
  1498. grow;
  1499. FPosnblock:=FLastblock;
  1500. end;
  1501. end;
  1502. until (i<left) or (maxlen=0);
  1503. end;
  1504. procedure tdynamicarray.writestream(f:TCStream);
  1505. var
  1506. hp : pdynamicblock;
  1507. begin
  1508. hp:=FFirstblock;
  1509. while assigned(hp) do
  1510. begin
  1511. f.Write(hp^.data,hp^.used);
  1512. hp:=hp^.Next;
  1513. end;
  1514. end;
  1515. end.
  1516. {
  1517. $Log$
  1518. Revision 1.7 2001-05-04 19:50:04 peter
  1519. * fixed dynamicarray.seek() with pos equals multiple of $10000
  1520. Revision 1.6 2001/04/13 01:22:06 peter
  1521. * symtable change to classes
  1522. * range check generation and errors fixed, make cycle DEBUG=1 works
  1523. * memory leaks fixed
  1524. Revision 1.5 2001/03/13 18:45:06 peter
  1525. * fixed some memory leaks
  1526. Revision 1.4 2001/03/05 21:40:01 peter
  1527. * fixed tdynamicarray.readstream
  1528. Revision 1.3 2000/12/29 21:57:27 peter
  1529. * 'classified' tdictionary, but leave it within an define
  1530. Revision 1.2 2000/12/25 00:07:25 peter
  1531. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1532. tlinkedlist objects)
  1533. Revision 1.1 2000/12/24 12:25:31 peter
  1534. + cstreams unit
  1535. * dynamicarray object to class
  1536. }