cclasses.pas 52 KB

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