cclasses.pas 52 KB

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