cclasses.pas 51 KB

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