cclasses.pas 54 KB

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