cclasses.pas 50 KB

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