cclasses.pas 53 KB

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