cclasses.pas 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351
  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. TList (Copied from FCL, exception handling stripped)
  41. ********************************************************}
  42. const
  43. MaxListSize = Maxint div 16;
  44. SListIndexError = 'List index exceeds bounds (%d)';
  45. SListCapacityError = 'The maximum list capacity is reached (%d)';
  46. SListCountError = 'List count too large (%d)';
  47. type
  48. { TList class }
  49. PPointerList = ^TPointerList;
  50. TPointerList = array[0..MaxListSize - 1] of Pointer;
  51. TListSortCompare = function (Item1, Item2: Pointer): Integer;
  52. TList = class(TObject)
  53. private
  54. FList: PPointerList;
  55. FCount: Integer;
  56. FCapacity: Integer;
  57. protected
  58. function Get(Index: Integer): Pointer;
  59. procedure Grow; virtual;
  60. procedure Put(Index: Integer; Item: Pointer);
  61. procedure SetCapacity(NewCapacity: Integer);
  62. procedure SetCount(NewCount: Integer);
  63. public
  64. destructor Destroy; override;
  65. function Add(Item: Pointer): Integer;
  66. procedure Clear; dynamic;
  67. procedure Delete(Index: Integer);
  68. class procedure Error(const Msg: string; Data: Integer); virtual;
  69. procedure Exchange(Index1, Index2: Integer);
  70. function Expand: TList;
  71. function Extract(item: Pointer): Pointer;
  72. function First: Pointer;
  73. procedure Assign(Obj:TList);
  74. function IndexOf(Item: Pointer): Integer;
  75. procedure Insert(Index: Integer; Item: Pointer);
  76. function Last: Pointer;
  77. procedure Move(CurIndex, NewIndex: Integer);
  78. function Remove(Item: Pointer): Integer;
  79. procedure Pack;
  80. procedure Sort(Compare: TListSortCompare);
  81. property Capacity: Integer read FCapacity write SetCapacity;
  82. property Count: Integer read FCount write SetCount;
  83. property Items[Index: Integer]: Pointer read Get write Put; default;
  84. property List: PPointerList read FList;
  85. end;
  86. {********************************************
  87. TLinkedList
  88. ********************************************}
  89. type
  90. TLinkedListItem = class
  91. public
  92. Previous,
  93. Next : TLinkedListItem;
  94. Constructor Create;
  95. Destructor Destroy;override;
  96. Function GetCopy:TLinkedListItem;virtual;
  97. end;
  98. TLinkedListItemClass = class of TLinkedListItem;
  99. TLinkedList = class
  100. private
  101. FCount : integer;
  102. FFirst,
  103. FLast : TLinkedListItem;
  104. FNoClear : boolean;
  105. public
  106. constructor Create;
  107. destructor Destroy;override;
  108. { true when the List is empty }
  109. function Empty:boolean;
  110. { deletes all Items }
  111. procedure Clear;
  112. { inserts an Item }
  113. procedure Insert(Item:TLinkedListItem);
  114. { inserts an Item before Loc }
  115. procedure InsertBefore(Item,Loc : TLinkedListItem);
  116. { inserts an Item after Loc }
  117. procedure InsertAfter(Item,Loc : TLinkedListItem);virtual;
  118. { concats an Item }
  119. procedure Concat(Item:TLinkedListItem);
  120. { deletes an Item }
  121. procedure Remove(Item:TLinkedListItem);
  122. { Gets First Item }
  123. function GetFirst:TLinkedListItem;
  124. { Gets last Item }
  125. function GetLast:TLinkedListItem;
  126. { inserts another List at the begin and make this List empty }
  127. procedure insertList(p : TLinkedList);
  128. { inserts another List after the provided item and make this List empty }
  129. procedure insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  130. { concats another List at the end and make this List empty }
  131. procedure concatList(p : TLinkedList);
  132. { concats another List at the start and makes a copy
  133. the list is ordered in reverse.
  134. }
  135. procedure insertListcopy(p : TLinkedList);
  136. { concats another List at the end and makes a copy }
  137. procedure concatListcopy(p : TLinkedList);
  138. property First:TLinkedListItem read FFirst;
  139. property Last:TLinkedListItem read FLast;
  140. property Count:Integer read FCount;
  141. property NoClear:boolean write FNoClear;
  142. end;
  143. {********************************************
  144. TStringList
  145. ********************************************}
  146. { string containerItem }
  147. TStringListItem = class(TLinkedListItem)
  148. FPStr : PString;
  149. public
  150. constructor Create(const s:string);
  151. destructor Destroy;override;
  152. function GetCopy:TLinkedListItem;override;
  153. function Str:string;
  154. end;
  155. { string container }
  156. TStringList = class(TLinkedList)
  157. private
  158. FDoubles : boolean; { if this is set to true, doubles are allowed }
  159. public
  160. constructor Create;
  161. constructor Create_No_Double;
  162. { inserts an Item }
  163. procedure Insert(const s:string);
  164. { concats an Item }
  165. procedure Concat(const s:string);
  166. { deletes an Item }
  167. procedure Remove(const s:string);
  168. { Gets First Item }
  169. function GetFirst:string;
  170. { Gets last Item }
  171. function GetLast:string;
  172. { true if string is in the container, compare case sensitive }
  173. function FindCase(const s:string):TStringListItem;
  174. { true if string is in the container }
  175. function Find(const s:string):TStringListItem;
  176. { inserts an item }
  177. procedure InsertItem(item:TStringListItem);
  178. { concats an item }
  179. procedure ConcatItem(item:TStringListItem);
  180. property Doubles:boolean read FDoubles write FDoubles;
  181. end;
  182. {********************************************
  183. Dictionary
  184. ********************************************}
  185. const
  186. { the real size will be [0..hasharray-1] ! }
  187. hasharraysize = 512;
  188. type
  189. { namedindexobect for use with dictionary and indexarray }
  190. TNamedIndexItem=class
  191. private
  192. { indexarray }
  193. FIndexNr : integer;
  194. FIndexNext : TNamedIndexItem;
  195. { dictionary }
  196. FLeft,
  197. FRight : TNamedIndexItem;
  198. FSpeedValue : cardinal;
  199. { singleList }
  200. FListNext : TNamedIndexItem;
  201. FName : Pstring;
  202. protected
  203. function GetName:string;virtual;
  204. procedure SetName(const n:string);virtual;
  205. public
  206. constructor Create;
  207. constructor CreateName(const n:string);
  208. destructor Destroy;override;
  209. property IndexNr:integer read FIndexNr write FIndexNr;
  210. property IndexNext:TNamedIndexItem read FIndexNext write FIndexNext;
  211. property Name:string read GetName write SetName;
  212. property SpeedValue:cardinal read FSpeedValue;
  213. property ListNext:TNamedIndexItem read FListNext;
  214. property Left:TNamedIndexItem read FLeft write FLeft;
  215. property Right:TNamedIndexItem read FRight write FRight;
  216. end;
  217. Pdictionaryhasharray=^Tdictionaryhasharray;
  218. Tdictionaryhasharray=array[0..hasharraysize-1] of TNamedIndexItem;
  219. TnamedIndexCallback = procedure(p:TNamedIndexItem;arg:pointer) of object;
  220. TnamedIndexStaticCallback = procedure(p:TNamedIndexItem;arg:pointer);
  221. Tdictionary=class
  222. private
  223. FRoot : TNamedIndexItem;
  224. FCount : longint;
  225. FHashArray : Pdictionaryhasharray;
  226. procedure cleartree(var obj:TNamedIndexItem);
  227. function insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  228. procedure inserttree(currtree,currroot:TNamedIndexItem);
  229. public
  230. noclear : boolean;
  231. delete_doubles : boolean;
  232. constructor Create;
  233. destructor Destroy;override;
  234. procedure usehash;
  235. procedure clear;
  236. function delete(const s:string):TNamedIndexItem;
  237. function empty:boolean;
  238. procedure foreach(proc2call:TNamedIndexcallback;arg:pointer);
  239. procedure foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  240. function insert(obj:TNamedIndexItem):TNamedIndexItem;
  241. function replace(oldobj,newobj:TNamedIndexItem):boolean;
  242. function rename(const olds,News : string):TNamedIndexItem;
  243. function search(const s:string):TNamedIndexItem;
  244. function speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  245. property Items[const s:string]:TNamedIndexItem read Search;default;
  246. property Count:longint read FCount;
  247. end;
  248. tsingleList=class
  249. First,
  250. last : TNamedIndexItem;
  251. constructor Create;
  252. procedure reset;
  253. procedure clear;
  254. procedure insert(p:TNamedIndexItem);
  255. end;
  256. tindexobjectarray=array[1..16000] of TNamedIndexItem;
  257. pnamedindexobjectarray=^tindexobjectarray;
  258. tindexarray=class
  259. noclear : boolean;
  260. First : TNamedIndexItem;
  261. count : integer;
  262. constructor Create(Agrowsize:integer);
  263. destructor destroy;override;
  264. procedure clear;
  265. procedure foreach(proc2call : Tnamedindexcallback;arg:pointer);
  266. procedure foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  267. procedure deleteindex(p:TNamedIndexItem);
  268. procedure delete(var p:TNamedIndexItem);
  269. procedure insert(p:TNamedIndexItem);
  270. procedure replace(oldp,newp:TNamedIndexItem);
  271. function search(nr:integer):TNamedIndexItem;
  272. private
  273. growsize,
  274. size : integer;
  275. data : pnamedindexobjectarray;
  276. procedure grow(gsize:integer);
  277. end;
  278. {********************************************
  279. DynamicArray
  280. ********************************************}
  281. const
  282. dynamicblockbasesize = 12;
  283. type
  284. pdynamicblock = ^tdynamicblock;
  285. tdynamicblock = record
  286. pos,
  287. used : integer;
  288. Next : pdynamicblock;
  289. { can't use sizeof(integer) because it crashes gdb }
  290. data : array[0..1024*1024] of byte;
  291. end;
  292. tdynamicarray = class
  293. private
  294. FPosn : integer;
  295. FPosnblock : pdynamicblock;
  296. FBlocksize : integer;
  297. FFirstblock,
  298. FLastblock : pdynamicblock;
  299. procedure grow;
  300. public
  301. constructor Create(Ablocksize:integer);
  302. destructor Destroy;override;
  303. procedure reset;
  304. function size:integer;
  305. procedure align(i:integer);
  306. procedure seek(i:integer);
  307. function read(var d;len:integer):integer;
  308. procedure write(const d;len:integer);
  309. procedure writestr(const s:string);
  310. procedure readstream(f:TCStream;maxlen:longint);
  311. procedure writestream(f:TCStream);
  312. property BlockSize : integer read FBlocksize;
  313. property FirstBlock : PDynamicBlock read FFirstBlock;
  314. property Pos : integer read FPosn;
  315. end;
  316. implementation
  317. {*****************************************************************************
  318. Memory debug
  319. *****************************************************************************}
  320. constructor tmemdebug.create(const s:string);
  321. begin
  322. infostr:=s;
  323. totalmem:=0;
  324. Start;
  325. end;
  326. procedure tmemdebug.start;
  327. begin
  328. {$ifdef Delphi}
  329. startmem:=0;
  330. {$else}
  331. startmem:=memavail;
  332. {$endif Delphi}
  333. end;
  334. procedure tmemdebug.stop;
  335. begin
  336. if startmem<>0 then
  337. begin
  338. {$ifndef Delphi}
  339. inc(TotalMem,memavail-startmem);
  340. {$endif}
  341. startmem:=0;
  342. end;
  343. end;
  344. destructor tmemdebug.destroy;
  345. begin
  346. Stop;
  347. show;
  348. end;
  349. procedure tmemdebug.show;
  350. begin
  351. {$ifndef Delphi}
  352. write('memory [',infostr,'] ');
  353. if TotalMem>0 then
  354. writeln(DStr(TotalMem shr 10),' Kb released')
  355. else
  356. writeln(DStr((-TotalMem) shr 10),' Kb allocated');
  357. {$endif Delphi}
  358. end;
  359. {*****************************************************************************
  360. TList
  361. *****************************************************************************}
  362. Const
  363. // Ratio of Pointer and Word Size.
  364. WordRatio = SizeOf(Pointer) Div SizeOf(Word);
  365. function TList.Get(Index: Integer): Pointer;
  366. begin
  367. If (Index<0) or (Index>=FCount) then
  368. Error(SListIndexError,Index);
  369. Result:=FList^[Index];
  370. end;
  371. procedure TList.Grow;
  372. begin
  373. // Only for compatibility with Delphi. Not needed.
  374. end;
  375. procedure TList.Put(Index: Integer; Item: Pointer);
  376. begin
  377. if (Index<0) or (Index>=FCount) then
  378. Error(SListIndexError,Index);
  379. Flist^[Index]:=Item;
  380. end;
  381. function TList.Extract(item: Pointer): Pointer;
  382. var
  383. i : Integer;
  384. begin
  385. result:=nil;
  386. i:=IndexOf(item);
  387. if i>=0 then
  388. begin
  389. Result:=item;
  390. FList^[i]:=nil;
  391. Delete(i);
  392. end;
  393. end;
  394. procedure TList.SetCapacity(NewCapacity: Integer);
  395. Var NewList,ToFree : PPointerList;
  396. begin
  397. If (NewCapacity<0) or (NewCapacity>MaxListSize) then
  398. Error (SListCapacityError,NewCapacity);
  399. if NewCapacity=FCapacity then
  400. exit;
  401. ReallocMem(FList,SizeOf(Pointer)*NewCapacity);
  402. FCapacity:=NewCapacity;
  403. end;
  404. procedure TList.SetCount(NewCount: Integer);
  405. begin
  406. If (NewCount<0) or (NewCount>MaxListSize)then
  407. Error(SListCountError,NewCount);
  408. If NewCount<FCount then
  409. FCount:=NewCount
  410. else If NewCount>FCount then
  411. begin
  412. If NewCount>FCapacity then
  413. SetCapacity (NewCount);
  414. If FCount<NewCount then
  415. FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
  416. FCount:=Newcount;
  417. end;
  418. end;
  419. destructor TList.Destroy;
  420. begin
  421. Self.Clear;
  422. inherited Destroy;
  423. end;
  424. Function TList.Add(Item: Pointer): Integer;
  425. begin
  426. Self.Insert (Count,Item);
  427. Result:=Count-1;
  428. end;
  429. Procedure TList.Clear;
  430. begin
  431. If Assigned(FList) then
  432. begin
  433. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  434. FList:=Nil;
  435. FCapacity:=0;
  436. FCount:=0;
  437. end;
  438. end;
  439. Procedure TList.Delete(Index: Integer);
  440. Var
  441. OldPointer :Pointer;
  442. begin
  443. If (Index<0) or (Index>=FCount) then
  444. Error (SListIndexError,Index);
  445. FCount:=FCount-1;
  446. OldPointer:=Flist^[Index];
  447. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  448. // Shrink the list if appropiate
  449. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  450. begin
  451. FCapacity := FCapacity shr 1;
  452. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  453. end;
  454. end;
  455. class procedure TList.Error(const Msg: string; Data: Integer);
  456. var
  457. s:string;
  458. p:longint;
  459. begin
  460. p:=pos('%d',Msg);
  461. writeln(copy(Msg,1,pred(p)),Data,copy(Msg,p+3,255));
  462. end;
  463. procedure TList.Exchange(Index1, Index2: Integer);
  464. var Temp : Pointer;
  465. begin
  466. If ((Index1>=FCount) or (Index1<0)) then
  467. Error(SListIndexError,Index1);
  468. If ((Index2>=FCount) or (Index2<0)) then
  469. Error(SListIndexError,Index2);
  470. Temp:=FList^[Index1];
  471. FList^[Index1]:=FList^[Index2];
  472. FList^[Index2]:=Temp;
  473. end;
  474. function TList.Expand: TList;
  475. Var IncSize : Longint;
  476. begin
  477. if FCount<FCapacity then exit;
  478. IncSize:=4;
  479. if FCapacity>3 then IncSize:=IncSize+4;
  480. if FCapacity>8 then IncSize:=IncSize+8;
  481. if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
  482. SetCapacity(FCapacity+IncSize);
  483. Result:=Self;
  484. end;
  485. function TList.First: Pointer;
  486. begin
  487. If FCount=0 then
  488. Result:=Nil
  489. else
  490. Result:=Items[0];
  491. end;
  492. function TList.IndexOf(Item: Pointer): Integer;
  493. begin
  494. Result:=0;
  495. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  496. If Result=FCount then Result:=-1;
  497. end;
  498. procedure TList.Insert(Index: Integer; Item: Pointer);
  499. begin
  500. If (Index<0) or (Index>FCount )then
  501. Error(SlistIndexError,Index);
  502. IF FCount=FCapacity Then Self.Expand;
  503. If Index<FCount then
  504. System.Move(Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  505. FList^[Index]:=Item;
  506. FCount:=FCount+1;
  507. end;
  508. function TList.Last: Pointer;
  509. begin
  510. // Wouldn't it be better to return nil if the count is zero ?
  511. If FCount=0 then
  512. Result:=Nil
  513. else
  514. Result:=Items[FCount-1];
  515. end;
  516. procedure TList.Move(CurIndex, NewIndex: Integer);
  517. Var Temp : Pointer;
  518. begin
  519. If ((CurIndex<0) or (CurIndex>Count-1)) then
  520. Error(SListIndexError,CurIndex);
  521. If (NewINdex<0) then
  522. Error(SlistIndexError,NewIndex);
  523. Temp:=FList^[CurIndex];
  524. FList^[CurIndex]:=Nil;
  525. Self.Delete(CurIndex);
  526. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  527. // Newindex changes when deleting ??
  528. Self.Insert (NewIndex,Nil);
  529. FList^[NewIndex]:=Temp;
  530. end;
  531. function TList.Remove(Item: Pointer): Integer;
  532. begin
  533. Result:=IndexOf(Item);
  534. If Result<>-1 then
  535. Self.Delete (Result);
  536. end;
  537. Procedure TList.Pack;
  538. Var {Last,I,J,}Runner : Longint;
  539. begin
  540. // Not the fastest; but surely correct
  541. For Runner:=Fcount-1 downto 0 do
  542. if Items[Runner]=Nil then Self.Delete(Runner);
  543. { The following may be faster in case of large and defragmented lists
  544. If count=0 then exit;
  545. Runner:=0;I:=0;
  546. TheLast:=Count;
  547. while runner<count do
  548. begin
  549. // Find first Nil
  550. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  551. if Runner<Count do
  552. begin
  553. // Start searching for non-nil from last known nil+1
  554. if i<Runner then I:=Runner+1;
  555. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  556. // Start looking for last non-nil of block.
  557. J:=I+1;
  558. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  559. // Move block and zero out
  560. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  561. FillWord (Flist^[I],(J-I)*WordRatio,0);
  562. // Update Runner and Last to point behind last block
  563. TheLast:=Runner+(J-I);
  564. If J=Count then
  565. begin
  566. // Shortcut, when J=Count we checked all pointers
  567. Runner:=Count
  568. else
  569. begin
  570. Runner:=TheLast;
  571. I:=j;
  572. end;
  573. end;
  574. Count:=TheLast;
  575. }
  576. end;
  577. // Needed by Sort method.
  578. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  579. Compare : TListSortCompare);
  580. Var I,J : Longint;
  581. P,Q : Pointer;
  582. begin
  583. Repeat
  584. I:=L;
  585. J:=R;
  586. P:=FList^[ (L+R) div 2 ];
  587. repeat
  588. While Compare(P,FList^[i])>0 Do I:=I+1;
  589. While Compare(P,FList^[J])<0 Do J:=J-1;
  590. If I<=J then
  591. begin
  592. Q:=Flist^[I];
  593. Flist^[I]:=FList^[J];
  594. FList^[J]:=Q;
  595. I:=I+1;
  596. J:=j-1;
  597. end;
  598. Until I>J;
  599. If L<J then QuickSort (FList,L,J,Compare);
  600. L:=I;
  601. Until I>=R;
  602. end;
  603. procedure TList.Sort(Compare: TListSortCompare);
  604. begin
  605. If Not Assigned(FList) or (FCount<2) then exit;
  606. QuickSort (Flist, 0, FCount-1,Compare);
  607. end;
  608. procedure TList.Assign(Obj:TList);
  609. // Principle copied from TCollection
  610. var i : Integer;
  611. begin
  612. Clear;
  613. For I:=0 To Obj.Count-1 Do
  614. Add(Obj[i]);
  615. end;
  616. {****************************************************************************
  617. TLinkedListItem
  618. ****************************************************************************}
  619. constructor TLinkedListItem.Create;
  620. begin
  621. Previous:=nil;
  622. Next:=nil;
  623. end;
  624. destructor TLinkedListItem.Destroy;
  625. begin
  626. end;
  627. function TLinkedListItem.GetCopy:TLinkedListItem;
  628. var
  629. p : TLinkedListItem;
  630. l : integer;
  631. begin
  632. p:=TLinkedListItemClass(ClassType).Create;
  633. l:=InstanceSize;
  634. Move(pointer(self)^,pointer(p)^,l);
  635. Result:=p;
  636. end;
  637. {****************************************************************************
  638. TLinkedList
  639. ****************************************************************************}
  640. constructor TLinkedList.Create;
  641. begin
  642. FFirst:=nil;
  643. Flast:=nil;
  644. FCount:=0;
  645. FNoClear:=False;
  646. end;
  647. destructor TLinkedList.destroy;
  648. begin
  649. if not FNoClear then
  650. Clear;
  651. end;
  652. function TLinkedList.empty:boolean;
  653. begin
  654. Empty:=(FFirst=nil);
  655. end;
  656. procedure TLinkedList.Insert(Item:TLinkedListItem);
  657. begin
  658. if FFirst=nil then
  659. begin
  660. FLast:=Item;
  661. Item.Previous:=nil;
  662. Item.Next:=nil;
  663. end
  664. else
  665. begin
  666. FFirst.Previous:=Item;
  667. Item.Previous:=nil;
  668. Item.Next:=FFirst;
  669. end;
  670. FFirst:=Item;
  671. inc(FCount);
  672. end;
  673. procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
  674. begin
  675. Item.Previous:=Loc.Previous;
  676. Item.Next:=Loc;
  677. Loc.Previous:=Item;
  678. if assigned(Item.Previous) then
  679. Item.Previous.Next:=Item
  680. else
  681. { if we've no next item, we've to adjust FFist }
  682. FFirst:=Item;
  683. inc(FCount);
  684. end;
  685. procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
  686. begin
  687. Item.Next:=Loc.Next;
  688. Loc.Next:=Item;
  689. Item.Previous:=Loc;
  690. if assigned(Item.Next) then
  691. Item.Next.Previous:=Item
  692. else
  693. { if we've no next item, we've to adjust FLast }
  694. FLast:=Item;
  695. inc(FCount);
  696. end;
  697. procedure TLinkedList.Concat(Item:TLinkedListItem);
  698. begin
  699. if FFirst=nil then
  700. begin
  701. FFirst:=Item;
  702. Item.Previous:=nil;
  703. Item.Next:=nil;
  704. end
  705. else
  706. begin
  707. Flast.Next:=Item;
  708. Item.Previous:=Flast;
  709. Item.Next:=nil;
  710. end;
  711. Flast:=Item;
  712. inc(FCount);
  713. end;
  714. procedure TLinkedList.remove(Item:TLinkedListItem);
  715. begin
  716. if Item=nil then
  717. exit;
  718. if (FFirst=Item) and (Flast=Item) then
  719. begin
  720. FFirst:=nil;
  721. Flast:=nil;
  722. end
  723. else if FFirst=Item then
  724. begin
  725. FFirst:=Item.Next;
  726. if assigned(FFirst) then
  727. FFirst.Previous:=nil;
  728. end
  729. else if Flast=Item then
  730. begin
  731. Flast:=Flast.Previous;
  732. if assigned(Flast) then
  733. Flast.Next:=nil;
  734. end
  735. else
  736. begin
  737. Item.Previous.Next:=Item.Next;
  738. Item.Next.Previous:=Item.Previous;
  739. end;
  740. Item.Next:=nil;
  741. Item.Previous:=nil;
  742. dec(FCount);
  743. end;
  744. procedure TLinkedList.clear;
  745. var
  746. NewNode : TLinkedListItem;
  747. begin
  748. NewNode:=FFirst;
  749. while assigned(NewNode) do
  750. begin
  751. FFirst:=NewNode.Next;
  752. NewNode.Free;
  753. NewNode:=FFirst;
  754. end;
  755. FLast:=nil;
  756. FFirst:=nil;
  757. FCount:=0;
  758. end;
  759. function TLinkedList.GetFirst:TLinkedListItem;
  760. begin
  761. if FFirst=nil then
  762. GetFirst:=nil
  763. else
  764. begin
  765. GetFirst:=FFirst;
  766. if FFirst=FLast then
  767. FLast:=nil;
  768. FFirst:=FFirst.Next;
  769. dec(FCount);
  770. end;
  771. end;
  772. function TLinkedList.GetLast:TLinkedListItem;
  773. begin
  774. if FLast=nil then
  775. Getlast:=nil
  776. else
  777. begin
  778. Getlast:=FLast;
  779. if FLast=FFirst then
  780. FFirst:=nil;
  781. FLast:=FLast.Previous;
  782. dec(FCount);
  783. end;
  784. end;
  785. procedure TLinkedList.insertList(p : TLinkedList);
  786. begin
  787. { empty List ? }
  788. if (p.FFirst=nil) then
  789. exit;
  790. p.Flast.Next:=FFirst;
  791. { we have a double Linked List }
  792. if assigned(FFirst) then
  793. FFirst.Previous:=p.Flast;
  794. FFirst:=p.FFirst;
  795. if (FLast=nil) then
  796. Flast:=p.Flast;
  797. inc(FCount,p.FCount);
  798. { p becomes empty }
  799. p.FFirst:=nil;
  800. p.Flast:=nil;
  801. p.FCount:=0;
  802. end;
  803. procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  804. begin
  805. { empty List ? }
  806. if (p.FFirst=nil) then
  807. exit;
  808. if (Item=nil) then
  809. begin
  810. { Insert at begin }
  811. InsertList(p);
  812. exit;
  813. end
  814. else
  815. begin
  816. p.FFirst.Previous:=Item;
  817. p.FLast.Next:=Item.Next;
  818. if assigned(Item.Next) then
  819. Item.Next.Previous:=p.FLast
  820. else
  821. FLast:=p.FLast;
  822. Item.Next:=p.FFirst;
  823. inc(FCount,p.FCount);
  824. end;
  825. { p becomes empty }
  826. p.FFirst:=nil;
  827. p.Flast:=nil;
  828. p.FCount:=0;
  829. end;
  830. procedure TLinkedList.concatList(p : TLinkedList);
  831. begin
  832. if (p.FFirst=nil) then
  833. exit;
  834. if FFirst=nil then
  835. FFirst:=p.FFirst
  836. else
  837. begin
  838. FLast.Next:=p.FFirst;
  839. p.FFirst.Previous:=Flast;
  840. end;
  841. Flast:=p.Flast;
  842. inc(FCount,p.FCount);
  843. { make p empty }
  844. p.Flast:=nil;
  845. p.FFirst:=nil;
  846. p.FCount:=0;
  847. end;
  848. procedure TLinkedList.insertListcopy(p : TLinkedList);
  849. var
  850. NewNode,NewNode2 : TLinkedListItem;
  851. begin
  852. NewNode:=p.First;
  853. while assigned(NewNode) do
  854. begin
  855. NewNode2:=NewNode.Getcopy;
  856. if assigned(NewNode2) then
  857. Insert(NewNode2);
  858. NewNode:=NewNode.Next;
  859. end;
  860. end;
  861. procedure TLinkedList.concatListcopy(p : TLinkedList);
  862. var
  863. NewNode,NewNode2 : TLinkedListItem;
  864. begin
  865. NewNode:=p.First;
  866. while assigned(NewNode) do
  867. begin
  868. NewNode2:=NewNode.Getcopy;
  869. if assigned(NewNode2) then
  870. Concat(NewNode2);
  871. NewNode:=NewNode.Next;
  872. end;
  873. end;
  874. {****************************************************************************
  875. TStringListItem
  876. ****************************************************************************}
  877. constructor TStringListItem.Create(const s:string);
  878. begin
  879. inherited Create;
  880. FPStr:=stringdup(s);
  881. end;
  882. destructor TStringListItem.Destroy;
  883. begin
  884. stringdispose(FPStr);
  885. end;
  886. function TStringListItem.Str:string;
  887. begin
  888. Str:=FPStr^;
  889. end;
  890. function TStringListItem.GetCopy:TLinkedListItem;
  891. begin
  892. Result:=(inherited GetCopy);
  893. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  894. end;
  895. {****************************************************************************
  896. TSTRINGList
  897. ****************************************************************************}
  898. constructor tstringList.Create;
  899. begin
  900. inherited Create;
  901. FDoubles:=true;
  902. end;
  903. constructor tstringList.Create_no_double;
  904. begin
  905. inherited Create;
  906. FDoubles:=false;
  907. end;
  908. procedure tstringList.insert(const s : string);
  909. begin
  910. if (s='') or
  911. ((not FDoubles) and (find(s)<>nil)) then
  912. exit;
  913. inherited insert(tstringListItem.create(s));
  914. end;
  915. procedure tstringList.concat(const s : string);
  916. begin
  917. if (s='') or
  918. ((not FDoubles) and (find(s)<>nil)) then
  919. exit;
  920. inherited concat(tstringListItem.create(s));
  921. end;
  922. procedure tstringList.remove(const s : string);
  923. var
  924. p : tstringListItem;
  925. begin
  926. if s='' then
  927. exit;
  928. p:=find(s);
  929. if assigned(p) then
  930. begin
  931. inherited Remove(p);
  932. p.Free;
  933. end;
  934. end;
  935. function tstringList.GetFirst : string;
  936. var
  937. p : tstringListItem;
  938. begin
  939. p:=tstringListItem(inherited GetFirst);
  940. if p=nil then
  941. GetFirst:=''
  942. else
  943. begin
  944. GetFirst:=p.FPStr^;
  945. p.free;
  946. end;
  947. end;
  948. function tstringList.Getlast : string;
  949. var
  950. p : tstringListItem;
  951. begin
  952. p:=tstringListItem(inherited Getlast);
  953. if p=nil then
  954. Getlast:=''
  955. else
  956. begin
  957. Getlast:=p.FPStr^;
  958. p.free;
  959. end;
  960. end;
  961. function tstringList.FindCase(const s:string):TstringListItem;
  962. var
  963. NewNode : tstringListItem;
  964. begin
  965. result:=nil;
  966. if s='' then
  967. exit;
  968. NewNode:=tstringListItem(FFirst);
  969. while assigned(NewNode) do
  970. begin
  971. if NewNode.FPStr^=s then
  972. begin
  973. result:=NewNode;
  974. exit;
  975. end;
  976. NewNode:=tstringListItem(NewNode.Next);
  977. end;
  978. end;
  979. function tstringList.Find(const s:string):TstringListItem;
  980. var
  981. NewNode : tstringListItem;
  982. ups : string;
  983. begin
  984. result:=nil;
  985. if s='' then
  986. exit;
  987. ups:=upper(s);
  988. NewNode:=tstringListItem(FFirst);
  989. while assigned(NewNode) do
  990. begin
  991. if upper(NewNode.FPStr^)=ups then
  992. begin
  993. result:=NewNode;
  994. exit;
  995. end;
  996. NewNode:=tstringListItem(NewNode.Next);
  997. end;
  998. end;
  999. procedure TStringList.InsertItem(item:TStringListItem);
  1000. begin
  1001. inherited Insert(item);
  1002. end;
  1003. procedure TStringList.ConcatItem(item:TStringListItem);
  1004. begin
  1005. inherited Concat(item);
  1006. end;
  1007. {****************************************************************************
  1008. TNamedIndexItem
  1009. ****************************************************************************}
  1010. constructor TNamedIndexItem.Create;
  1011. begin
  1012. { index }
  1013. Findexnr:=-1;
  1014. FindexNext:=nil;
  1015. { dictionary }
  1016. Fleft:=nil;
  1017. Fright:=nil;
  1018. FName:=nil;
  1019. Fspeedvalue:=cardinal($ffffffff);
  1020. { List }
  1021. FListNext:=nil;
  1022. end;
  1023. constructor TNamedIndexItem.Createname(const n:string);
  1024. begin
  1025. { index }
  1026. Findexnr:=-1;
  1027. FindexNext:=nil;
  1028. { dictionary }
  1029. Fleft:=nil;
  1030. Fright:=nil;
  1031. fspeedvalue:=getspeedvalue(n);
  1032. {$ifdef compress}
  1033. FName:=stringdup(minilzw_encode(n));
  1034. {$else}
  1035. FName:=stringdup(n);
  1036. {$endif}
  1037. { List }
  1038. FListNext:=nil;
  1039. end;
  1040. destructor TNamedIndexItem.destroy;
  1041. begin
  1042. stringdispose(FName);
  1043. end;
  1044. procedure TNamedIndexItem.setname(const n:string);
  1045. begin
  1046. if assigned(FName) then
  1047. stringdispose(FName);
  1048. fspeedvalue:=getspeedvalue(n);
  1049. {$ifdef compress}
  1050. FName:=stringdup(minilzw_encode(n));
  1051. {$else}
  1052. FName:=stringdup(n);
  1053. {$endif}
  1054. end;
  1055. function TNamedIndexItem.GetName:string;
  1056. begin
  1057. if assigned(FName) then
  1058. {$ifdef compress}
  1059. Getname:=minilzw_decode(FName^)
  1060. {$else}
  1061. Getname:=FName^
  1062. {$endif}
  1063. else
  1064. Getname:='';
  1065. end;
  1066. {****************************************************************************
  1067. TDICTIONARY
  1068. ****************************************************************************}
  1069. constructor Tdictionary.Create;
  1070. begin
  1071. FRoot:=nil;
  1072. FHashArray:=nil;
  1073. noclear:=false;
  1074. delete_doubles:=false;
  1075. end;
  1076. procedure Tdictionary.usehash;
  1077. begin
  1078. if not(assigned(FRoot)) and
  1079. not(assigned(FHashArray)) then
  1080. begin
  1081. New(FHashArray);
  1082. fillchar(FHashArray^,sizeof(FHashArray^),0);
  1083. end;
  1084. end;
  1085. function counttree(p: tnamedindexitem): longint;
  1086. begin
  1087. counttree:=0;
  1088. if not assigned(p) then
  1089. exit;
  1090. result := 1;
  1091. inc(result,counttree(p.fleft));
  1092. inc(result,counttree(p.fright));
  1093. end;
  1094. destructor Tdictionary.destroy;
  1095. begin
  1096. if not noclear then
  1097. clear;
  1098. if assigned(FHashArray) then
  1099. begin
  1100. dispose(FHashArray);
  1101. end;
  1102. end;
  1103. procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
  1104. begin
  1105. if assigned(obj.Fleft) then
  1106. cleartree(obj.FLeft);
  1107. if assigned(obj.FRight) then
  1108. cleartree(obj.FRight);
  1109. obj.free;
  1110. obj:=nil;
  1111. end;
  1112. procedure Tdictionary.clear;
  1113. var
  1114. w : integer;
  1115. begin
  1116. if assigned(FRoot) then
  1117. cleartree(FRoot);
  1118. if assigned(FHashArray) then
  1119. for w:= low(FHashArray^) to high(FHashArray^) do
  1120. if assigned(FHashArray^[w]) then
  1121. cleartree(FHashArray^[w]);
  1122. end;
  1123. function Tdictionary.delete(const s:string):TNamedIndexItem;
  1124. var
  1125. p,SpeedValue : cardinal;
  1126. n : TNamedIndexItem;
  1127. {$ifdef compress}
  1128. senc:string;
  1129. {$else}
  1130. senc:string absolute s;
  1131. {$endif}
  1132. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  1133. begin
  1134. while root.FRight<>nil do
  1135. root:=root.FRight;
  1136. root.FRight:=Atree;
  1137. end;
  1138. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  1139. type
  1140. leftright=(left,right);
  1141. var
  1142. lr : leftright;
  1143. oldroot : TNamedIndexItem;
  1144. begin
  1145. oldroot:=nil;
  1146. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  1147. begin
  1148. oldroot:=root;
  1149. if SpeedValue<root.SpeedValue then
  1150. begin
  1151. root:=root.FRight;
  1152. lr:=right;
  1153. end
  1154. else
  1155. begin
  1156. root:=root.FLeft;
  1157. lr:=left;
  1158. end;
  1159. end;
  1160. while (root<>nil) and (root.FName^<>senc) do
  1161. begin
  1162. oldroot:=root;
  1163. if senc<root.FName^ then
  1164. begin
  1165. root:=root.FRight;
  1166. lr:=right;
  1167. end
  1168. else
  1169. begin
  1170. root:=root.FLeft;
  1171. lr:=left;
  1172. end;
  1173. end;
  1174. if root<>nil then
  1175. begin
  1176. dec(FCount);
  1177. if root.FLeft<>nil then
  1178. begin
  1179. { Now the Node pointing to root must point to the left
  1180. subtree of root. The right subtree of root must be
  1181. connected to the right bottom of the left subtree.}
  1182. if lr=left then
  1183. oldroot.FLeft:=root.FLeft
  1184. else
  1185. oldroot.FRight:=root.FLeft;
  1186. if root.FRight<>nil then
  1187. insert_right_bottom(root.FLeft,root.FRight);
  1188. end
  1189. else
  1190. begin
  1191. { There is no left subtree. So we can just replace the Node to
  1192. delete with the right subtree.}
  1193. if lr=left then
  1194. oldroot.FLeft:=root.FRight
  1195. else
  1196. oldroot.FRight:=root.FRight;
  1197. end;
  1198. end;
  1199. delete_from_tree:=root;
  1200. end;
  1201. begin
  1202. {$ifdef compress}
  1203. senc:=minilzw_encode(s);
  1204. {$endif}
  1205. SpeedValue:=GetSpeedValue(s);
  1206. n:=FRoot;
  1207. if assigned(FHashArray) then
  1208. begin
  1209. { First, check if the Node to delete directly located under
  1210. the hasharray.}
  1211. p:=SpeedValue mod hasharraysize;
  1212. n:=FHashArray^[p];
  1213. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  1214. (n.FName^=senc) then
  1215. begin
  1216. { The Node to delete is directly located under the
  1217. hasharray. Make the hasharray point to the left
  1218. subtree of the Node and place the right subtree on
  1219. the right-bottom of the left subtree.}
  1220. if n.FLeft<>nil then
  1221. begin
  1222. FHashArray^[p]:=n.FLeft;
  1223. if n.FRight<>nil then
  1224. insert_right_bottom(n.FLeft,n.FRight);
  1225. end
  1226. else
  1227. FHashArray^[p]:=n.FRight;
  1228. delete:=n;
  1229. dec(FCount);
  1230. exit;
  1231. end;
  1232. end
  1233. else
  1234. begin
  1235. { First check if the Node to delete is the root.}
  1236. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  1237. (n.FName^=senc) then
  1238. begin
  1239. if n.FLeft<>nil then
  1240. begin
  1241. FRoot:=n.FLeft;
  1242. if n.FRight<>nil then
  1243. insert_right_bottom(n.FLeft,n.FRight);
  1244. end
  1245. else
  1246. FRoot:=n.FRight;
  1247. delete:=n;
  1248. dec(FCount);
  1249. exit;
  1250. end;
  1251. end;
  1252. delete:=delete_from_tree(n);
  1253. end;
  1254. function Tdictionary.empty:boolean;
  1255. var
  1256. w : integer;
  1257. begin
  1258. if assigned(FHashArray) then
  1259. begin
  1260. empty:=false;
  1261. for w:=low(FHashArray^) to high(FHashArray^) do
  1262. if assigned(FHashArray^[w]) then
  1263. exit;
  1264. empty:=true;
  1265. end
  1266. else
  1267. empty:=(FRoot=nil);
  1268. end;
  1269. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
  1270. procedure a(p:TNamedIndexItem;arg:pointer);
  1271. begin
  1272. proc2call(p,arg);
  1273. if assigned(p.FLeft) then
  1274. a(p.FLeft,arg);
  1275. if assigned(p.FRight) then
  1276. a(p.FRight,arg);
  1277. end;
  1278. var
  1279. i : integer;
  1280. begin
  1281. if assigned(FHashArray) then
  1282. begin
  1283. for i:=low(FHashArray^) to high(FHashArray^) do
  1284. if assigned(FHashArray^[i]) then
  1285. a(FHashArray^[i],arg);
  1286. end
  1287. else
  1288. if assigned(FRoot) then
  1289. a(FRoot,arg);
  1290. end;
  1291. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  1292. procedure a(p:TNamedIndexItem;arg:pointer);
  1293. begin
  1294. proc2call(p,arg);
  1295. if assigned(p.FLeft) then
  1296. a(p.FLeft,arg);
  1297. if assigned(p.FRight) then
  1298. a(p.FRight,arg);
  1299. end;
  1300. var
  1301. i : integer;
  1302. begin
  1303. if assigned(FHashArray) then
  1304. begin
  1305. for i:=low(FHashArray^) to high(FHashArray^) do
  1306. if assigned(FHashArray^[i]) then
  1307. a(FHashArray^[i],arg);
  1308. end
  1309. else
  1310. if assigned(FRoot) then
  1311. a(FRoot,arg);
  1312. end;
  1313. function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
  1314. var
  1315. hp : TNamedIndexItem;
  1316. begin
  1317. hp:=nil;
  1318. Replace:=false;
  1319. { must be the same name and hash }
  1320. if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
  1321. (oldobj.FName^<>newobj.FName^) then
  1322. exit;
  1323. { copy tree info }
  1324. newobj.FLeft:=oldobj.FLeft;
  1325. newobj.FRight:=oldobj.FRight;
  1326. { update treeroot }
  1327. if assigned(FHashArray) then
  1328. begin
  1329. hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
  1330. if hp=oldobj then
  1331. begin
  1332. FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
  1333. hp:=nil;
  1334. end;
  1335. end
  1336. else
  1337. begin
  1338. hp:=FRoot;
  1339. if hp=oldobj then
  1340. begin
  1341. FRoot:=newobj;
  1342. hp:=nil;
  1343. end;
  1344. end;
  1345. { update parent entry }
  1346. while assigned(hp) do
  1347. begin
  1348. { is the node to replace the left or right, then
  1349. update this node and stop }
  1350. if hp.FLeft=oldobj then
  1351. begin
  1352. hp.FLeft:=newobj;
  1353. break;
  1354. end;
  1355. if hp.FRight=oldobj then
  1356. begin
  1357. hp.FRight:=newobj;
  1358. break;
  1359. end;
  1360. { First check SpeedValue, to allow a fast insert }
  1361. if hp.SpeedValue>oldobj.SpeedValue then
  1362. hp:=hp.FRight
  1363. else
  1364. if hp.SpeedValue<oldobj.SpeedValue then
  1365. hp:=hp.FLeft
  1366. else
  1367. begin
  1368. if (hp.FName^=oldobj.FName^) then
  1369. begin
  1370. { this can never happend, return error }
  1371. exit;
  1372. end
  1373. else
  1374. if oldobj.FName^>hp.FName^ then
  1375. hp:=hp.FLeft
  1376. else
  1377. hp:=hp.FRight;
  1378. end;
  1379. end;
  1380. Replace:=true;
  1381. end;
  1382. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  1383. begin
  1384. inc(FCount);
  1385. if assigned(FHashArray) then
  1386. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  1387. else
  1388. insert:=insertNode(obj,FRoot);
  1389. end;
  1390. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  1391. begin
  1392. if currNode=nil then
  1393. begin
  1394. currNode:=NewNode;
  1395. insertNode:=NewNode;
  1396. end
  1397. { First check SpeedValue, to allow a fast insert }
  1398. else
  1399. if currNode.SpeedValue>NewNode.SpeedValue then
  1400. insertNode:=insertNode(NewNode,currNode.FRight)
  1401. else
  1402. if currNode.SpeedValue<NewNode.SpeedValue then
  1403. insertNode:=insertNode(NewNode,currNode.FLeft)
  1404. else
  1405. begin
  1406. if currNode.FName^>NewNode.FName^ then
  1407. insertNode:=insertNode(NewNode,currNode.FRight)
  1408. else
  1409. if currNode.FName^<NewNode.FName^ then
  1410. insertNode:=insertNode(NewNode,currNode.FLeft)
  1411. else
  1412. begin
  1413. if (delete_doubles) and
  1414. assigned(currNode) then
  1415. begin
  1416. NewNode.FLeft:=currNode.FLeft;
  1417. NewNode.FRight:=currNode.FRight;
  1418. if delete_doubles then
  1419. begin
  1420. currnode.FLeft:=nil;
  1421. currnode.FRight:=nil;
  1422. currnode.free;
  1423. end;
  1424. currNode:=NewNode;
  1425. insertNode:=NewNode;
  1426. end
  1427. else
  1428. insertNode:=currNode;
  1429. end;
  1430. end;
  1431. end;
  1432. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  1433. begin
  1434. if assigned(currtree) then
  1435. begin
  1436. inserttree(currtree.FLeft,currroot);
  1437. inserttree(currtree.FRight,currroot);
  1438. currtree.FRight:=nil;
  1439. currtree.FLeft:=nil;
  1440. insertNode(currtree,currroot);
  1441. end;
  1442. end;
  1443. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  1444. var
  1445. spdval : cardinal;
  1446. lasthp,
  1447. hp,hp2,hp3 : TNamedIndexItem;
  1448. {$ifdef compress}
  1449. oldsenc,newsenc:string;
  1450. {$else}
  1451. oldsenc:string absolute olds;
  1452. newsenc:string absolute news;
  1453. {$endif}
  1454. begin
  1455. {$ifdef compress}
  1456. oldsenc:=minilzw_encode(olds);
  1457. newsenc:=minilzw_encode(news);
  1458. {$endif}
  1459. spdval:=GetSpeedValue(olds);
  1460. if assigned(FHashArray) then
  1461. hp:=FHashArray^[spdval mod hasharraysize]
  1462. else
  1463. hp:=FRoot;
  1464. lasthp:=nil;
  1465. while assigned(hp) do
  1466. begin
  1467. if spdval>hp.SpeedValue then
  1468. begin
  1469. lasthp:=hp;
  1470. hp:=hp.FLeft
  1471. end
  1472. else
  1473. if spdval<hp.SpeedValue then
  1474. begin
  1475. lasthp:=hp;
  1476. hp:=hp.FRight
  1477. end
  1478. else
  1479. begin
  1480. if (hp.FName^=oldsenc) then
  1481. begin
  1482. { Get in hp2 the replacer for the root or hasharr }
  1483. hp2:=hp.FLeft;
  1484. hp3:=hp.FRight;
  1485. if not assigned(hp2) then
  1486. begin
  1487. hp2:=hp.FRight;
  1488. hp3:=hp.FLeft;
  1489. end;
  1490. { remove entry from the tree }
  1491. if assigned(lasthp) then
  1492. begin
  1493. if lasthp.FLeft=hp then
  1494. lasthp.FLeft:=hp2
  1495. else
  1496. lasthp.FRight:=hp2;
  1497. end
  1498. else
  1499. begin
  1500. if assigned(FHashArray) then
  1501. FHashArray^[spdval mod hasharraysize]:=hp2
  1502. else
  1503. FRoot:=hp2;
  1504. end;
  1505. { reinsert the hp3 in the tree from hp2 }
  1506. inserttree(hp3,hp2);
  1507. { reset Node with New values }
  1508. hp.FLeft:=nil;
  1509. hp.FRight:=nil;
  1510. stringdispose(hp.FName);
  1511. hp.FName:=stringdup(newsenc);
  1512. hp.FSpeedValue:=GetSpeedValue(news);
  1513. { reinsert }
  1514. if assigned(FHashArray) then
  1515. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  1516. else
  1517. rename:=insertNode(hp,FRoot);
  1518. exit;
  1519. end
  1520. else
  1521. if oldsenc>hp.FName^ then
  1522. begin
  1523. lasthp:=hp;
  1524. hp:=hp.FLeft
  1525. end
  1526. else
  1527. begin
  1528. lasthp:=hp;
  1529. hp:=hp.FRight;
  1530. end;
  1531. end;
  1532. end;
  1533. result := nil;
  1534. end;
  1535. function Tdictionary.search(const s:string):TNamedIndexItem;
  1536. var t:string;
  1537. begin
  1538. search:=speedsearch(s,getspeedvalue(s));
  1539. end;
  1540. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  1541. var
  1542. NewNode:TNamedIndexItem;
  1543. {$ifdef compress}
  1544. decn:string;
  1545. {$endif}
  1546. begin
  1547. if assigned(FHashArray) then
  1548. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  1549. else
  1550. NewNode:=FRoot;
  1551. while assigned(NewNode) do
  1552. begin
  1553. if SpeedValue>NewNode.SpeedValue then
  1554. NewNode:=NewNode.FLeft
  1555. else
  1556. if SpeedValue<NewNode.SpeedValue then
  1557. NewNode:=NewNode.FRight
  1558. else
  1559. begin
  1560. {$ifdef compress}
  1561. decn:=minilzw_decode(newnode.fname^);
  1562. if (decn=s) then
  1563. begin
  1564. speedsearch:=NewNode;
  1565. exit;
  1566. end
  1567. else
  1568. if s>decn then
  1569. NewNode:=NewNode.FLeft
  1570. else
  1571. NewNode:=NewNode.FRight;
  1572. {$else}
  1573. if (NewNode.FName^=s) then
  1574. begin
  1575. speedsearch:=NewNode;
  1576. exit;
  1577. end
  1578. else
  1579. if s>NewNode.FName^ then
  1580. NewNode:=NewNode.FLeft
  1581. else
  1582. NewNode:=NewNode.FRight;
  1583. {$endif}
  1584. end;
  1585. end;
  1586. speedsearch:=nil;
  1587. end;
  1588. {****************************************************************************
  1589. tsingleList
  1590. ****************************************************************************}
  1591. constructor tsingleList.create;
  1592. begin
  1593. First:=nil;
  1594. last:=nil;
  1595. end;
  1596. procedure tsingleList.reset;
  1597. begin
  1598. First:=nil;
  1599. last:=nil;
  1600. end;
  1601. procedure tsingleList.clear;
  1602. var
  1603. hp,hp2 : TNamedIndexItem;
  1604. begin
  1605. hp:=First;
  1606. while assigned(hp) do
  1607. begin
  1608. hp2:=hp;
  1609. hp:=hp.FListNext;
  1610. hp2.free;
  1611. end;
  1612. First:=nil;
  1613. last:=nil;
  1614. end;
  1615. procedure tsingleList.insert(p:TNamedIndexItem);
  1616. begin
  1617. if not assigned(First) then
  1618. First:=p
  1619. else
  1620. last.FListNext:=p;
  1621. last:=p;
  1622. p.FListNext:=nil;
  1623. end;
  1624. {****************************************************************************
  1625. tindexarray
  1626. ****************************************************************************}
  1627. constructor tindexarray.create(Agrowsize:integer);
  1628. begin
  1629. growsize:=Agrowsize;
  1630. size:=0;
  1631. count:=0;
  1632. data:=nil;
  1633. First:=nil;
  1634. noclear:=false;
  1635. end;
  1636. destructor tindexarray.destroy;
  1637. begin
  1638. if assigned(data) then
  1639. begin
  1640. if not noclear then
  1641. clear;
  1642. freemem(data);
  1643. data:=nil;
  1644. end;
  1645. end;
  1646. function tindexarray.search(nr:integer):TNamedIndexItem;
  1647. begin
  1648. if nr<=count then
  1649. search:=data^[nr]
  1650. else
  1651. search:=nil;
  1652. end;
  1653. procedure tindexarray.clear;
  1654. var
  1655. i : integer;
  1656. begin
  1657. for i:=1 to count do
  1658. if assigned(data^[i]) then
  1659. begin
  1660. data^[i].free;
  1661. data^[i]:=nil;
  1662. end;
  1663. count:=0;
  1664. First:=nil;
  1665. end;
  1666. procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
  1667. var
  1668. i : integer;
  1669. begin
  1670. for i:=1 to count do
  1671. if assigned(data^[i]) then
  1672. proc2call(data^[i],arg);
  1673. end;
  1674. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  1675. var
  1676. i : integer;
  1677. begin
  1678. for i:=1 to count do
  1679. if assigned(data^[i]) then
  1680. proc2call(data^[i],arg);
  1681. end;
  1682. procedure tindexarray.grow(gsize:integer);
  1683. var
  1684. osize : integer;
  1685. begin
  1686. osize:=size;
  1687. inc(size,gsize);
  1688. reallocmem(data,size*sizeof(pointer));
  1689. fillchar(data^[osize+1],gsize*sizeof(pointer),0);
  1690. end;
  1691. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  1692. var
  1693. i : integer;
  1694. begin
  1695. i:=p.Findexnr;
  1696. { update counter }
  1697. if i=count then
  1698. dec(count);
  1699. { update Linked List }
  1700. while (i>0) do
  1701. begin
  1702. dec(i);
  1703. if (i>0) and assigned(data^[i]) then
  1704. begin
  1705. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  1706. break;
  1707. end;
  1708. end;
  1709. if i=0 then
  1710. First:=p.FindexNext;
  1711. data^[p.FIndexnr]:=nil;
  1712. { clear entry }
  1713. p.FIndexnr:=-1;
  1714. p.FIndexNext:=nil;
  1715. end;
  1716. procedure tindexarray.delete(var p:TNamedIndexItem);
  1717. begin
  1718. deleteindex(p);
  1719. p.free;
  1720. p:=nil;
  1721. end;
  1722. procedure tindexarray.insert(p:TNamedIndexItem);
  1723. var
  1724. i : integer;
  1725. begin
  1726. if p.FIndexnr=-1 then
  1727. begin
  1728. inc(count);
  1729. p.FIndexnr:=count;
  1730. end;
  1731. if p.FIndexnr>count then
  1732. count:=p.FIndexnr;
  1733. if count>size then
  1734. grow(((count div growsize)+1)*growsize);
  1735. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  1736. data^[p.FIndexnr]:=p;
  1737. { update Linked List backward }
  1738. i:=p.FIndexnr;
  1739. while (i>0) do
  1740. begin
  1741. dec(i);
  1742. if (i>0) and assigned(data^[i]) then
  1743. begin
  1744. data^[i].FIndexNext:=p;
  1745. break;
  1746. end;
  1747. end;
  1748. if i=0 then
  1749. First:=p;
  1750. { update Linked List forward }
  1751. i:=p.FIndexnr;
  1752. while (i<=count) do
  1753. begin
  1754. inc(i);
  1755. if (i<=count) and assigned(data^[i]) then
  1756. begin
  1757. p.FIndexNext:=data^[i];
  1758. exit;
  1759. end;
  1760. end;
  1761. if i>count then
  1762. p.FIndexNext:=nil;
  1763. end;
  1764. procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
  1765. var
  1766. i : integer;
  1767. begin
  1768. newp.FIndexnr:=oldp.FIndexnr;
  1769. newp.FIndexNext:=oldp.FIndexNext;
  1770. data^[newp.FIndexnr]:=newp;
  1771. if First=oldp then
  1772. First:=newp;
  1773. { update Linked List backward }
  1774. i:=newp.FIndexnr;
  1775. while (i>0) do
  1776. begin
  1777. dec(i);
  1778. if (i>0) and assigned(data^[i]) then
  1779. begin
  1780. data^[i].FIndexNext:=newp;
  1781. break;
  1782. end;
  1783. end;
  1784. end;
  1785. {****************************************************************************
  1786. tdynamicarray
  1787. ****************************************************************************}
  1788. constructor tdynamicarray.create(Ablocksize:integer);
  1789. begin
  1790. FPosn:=0;
  1791. FPosnblock:=nil;
  1792. FFirstblock:=nil;
  1793. FLastblock:=nil;
  1794. Fblocksize:=Ablocksize;
  1795. grow;
  1796. end;
  1797. destructor tdynamicarray.destroy;
  1798. var
  1799. hp : pdynamicblock;
  1800. begin
  1801. while assigned(FFirstblock) do
  1802. begin
  1803. hp:=FFirstblock;
  1804. FFirstblock:=FFirstblock^.Next;
  1805. Freemem(hp);
  1806. end;
  1807. end;
  1808. function tdynamicarray.size:integer;
  1809. begin
  1810. if assigned(FLastblock) then
  1811. size:=FLastblock^.pos+FLastblock^.used
  1812. else
  1813. size:=0;
  1814. end;
  1815. procedure tdynamicarray.reset;
  1816. var
  1817. hp : pdynamicblock;
  1818. begin
  1819. while assigned(FFirstblock) do
  1820. begin
  1821. hp:=FFirstblock;
  1822. FFirstblock:=FFirstblock^.Next;
  1823. Freemem(hp);
  1824. end;
  1825. FPosn:=0;
  1826. FPosnblock:=nil;
  1827. FFirstblock:=nil;
  1828. FLastblock:=nil;
  1829. grow;
  1830. end;
  1831. procedure tdynamicarray.grow;
  1832. var
  1833. nblock : pdynamicblock;
  1834. begin
  1835. Getmem(nblock,blocksize+dynamicblockbasesize);
  1836. if not assigned(FFirstblock) then
  1837. begin
  1838. FFirstblock:=nblock;
  1839. FPosnblock:=nblock;
  1840. nblock^.pos:=0;
  1841. end
  1842. else
  1843. begin
  1844. FLastblock^.Next:=nblock;
  1845. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1846. end;
  1847. nblock^.used:=0;
  1848. nblock^.Next:=nil;
  1849. fillchar(nblock^.data,blocksize,0);
  1850. FLastblock:=nblock;
  1851. end;
  1852. procedure tdynamicarray.align(i:integer);
  1853. var
  1854. j : integer;
  1855. begin
  1856. j:=(FPosn mod i);
  1857. if j<>0 then
  1858. begin
  1859. j:=i-j;
  1860. if FPosnblock^.used+j>blocksize then
  1861. begin
  1862. dec(j,blocksize-FPosnblock^.used);
  1863. FPosnblock^.used:=blocksize;
  1864. grow;
  1865. FPosnblock:=FLastblock;
  1866. end;
  1867. inc(FPosnblock^.used,j);
  1868. inc(FPosn,j);
  1869. end;
  1870. end;
  1871. procedure tdynamicarray.seek(i:integer);
  1872. begin
  1873. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  1874. begin
  1875. { set FPosnblock correct if the size is bigger then
  1876. the current block }
  1877. if FPosnblock^.pos>i then
  1878. FPosnblock:=FFirstblock;
  1879. while assigned(FPosnblock) do
  1880. begin
  1881. if FPosnblock^.pos+blocksize>i then
  1882. break;
  1883. FPosnblock:=FPosnblock^.Next;
  1884. end;
  1885. { not found ? then increase blocks }
  1886. if not assigned(FPosnblock) then
  1887. begin
  1888. repeat
  1889. { the current FLastblock is now also fully used }
  1890. FLastblock^.used:=blocksize;
  1891. grow;
  1892. FPosnblock:=FLastblock;
  1893. until FPosnblock^.pos+blocksize>=i;
  1894. end;
  1895. end;
  1896. FPosn:=i;
  1897. if FPosn mod blocksize>FPosnblock^.used then
  1898. FPosnblock^.used:=FPosn mod blocksize;
  1899. end;
  1900. procedure tdynamicarray.write(const d;len:integer);
  1901. var
  1902. p : pchar;
  1903. i,j : integer;
  1904. begin
  1905. p:=pchar(@d);
  1906. while (len>0) do
  1907. begin
  1908. i:=FPosn mod blocksize;
  1909. if i+len>=blocksize then
  1910. begin
  1911. j:=blocksize-i;
  1912. move(p^,FPosnblock^.data[i],j);
  1913. inc(p,j);
  1914. inc(FPosn,j);
  1915. dec(len,j);
  1916. FPosnblock^.used:=blocksize;
  1917. if assigned(FPosnblock^.Next) then
  1918. FPosnblock:=FPosnblock^.Next
  1919. else
  1920. begin
  1921. grow;
  1922. FPosnblock:=FLastblock;
  1923. end;
  1924. end
  1925. else
  1926. begin
  1927. move(p^,FPosnblock^.data[i],len);
  1928. inc(p,len);
  1929. inc(FPosn,len);
  1930. i:=FPosn mod blocksize;
  1931. if i>FPosnblock^.used then
  1932. FPosnblock^.used:=i;
  1933. len:=0;
  1934. end;
  1935. end;
  1936. end;
  1937. procedure tdynamicarray.writestr(const s:string);
  1938. begin
  1939. write(s[1],length(s));
  1940. end;
  1941. function tdynamicarray.read(var d;len:integer):integer;
  1942. var
  1943. p : pchar;
  1944. i,j,res : integer;
  1945. begin
  1946. res:=0;
  1947. p:=pchar(@d);
  1948. while (len>0) do
  1949. begin
  1950. i:=FPosn mod blocksize;
  1951. if i+len>=FPosnblock^.used then
  1952. begin
  1953. j:=FPosnblock^.used-i;
  1954. move(FPosnblock^.data[i],p^,j);
  1955. inc(p,j);
  1956. inc(FPosn,j);
  1957. inc(res,j);
  1958. dec(len,j);
  1959. if assigned(FPosnblock^.Next) then
  1960. FPosnblock:=FPosnblock^.Next
  1961. else
  1962. break;
  1963. end
  1964. else
  1965. begin
  1966. move(FPosnblock^.data[i],p^,len);
  1967. inc(p,len);
  1968. inc(FPosn,len);
  1969. inc(res,len);
  1970. len:=0;
  1971. end;
  1972. end;
  1973. read:=res;
  1974. end;
  1975. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  1976. var
  1977. i,left : integer;
  1978. begin
  1979. if maxlen=-1 then
  1980. maxlen:=maxlongint;
  1981. repeat
  1982. left:=blocksize-FPosnblock^.used;
  1983. if left>maxlen then
  1984. left:=maxlen;
  1985. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  1986. dec(maxlen,i);
  1987. inc(FPosnblock^.used,i);
  1988. if FPosnblock^.used=blocksize then
  1989. begin
  1990. if assigned(FPosnblock^.Next) then
  1991. FPosnblock:=FPosnblock^.Next
  1992. else
  1993. begin
  1994. grow;
  1995. FPosnblock:=FLastblock;
  1996. end;
  1997. end;
  1998. until (i<left) or (maxlen=0);
  1999. end;
  2000. procedure tdynamicarray.writestream(f:TCStream);
  2001. var
  2002. hp : pdynamicblock;
  2003. begin
  2004. hp:=FFirstblock;
  2005. while assigned(hp) do
  2006. begin
  2007. f.Write(hp^.data,hp^.used);
  2008. hp:=hp^.Next;
  2009. end;
  2010. end;
  2011. end.
  2012. {
  2013. $Log$
  2014. Revision 1.36 2004-09-13 20:26:26 peter
  2015. * stringlist.find case insensitive
  2016. Revision 1.35 2004/06/20 08:55:28 florian
  2017. * logs truncated
  2018. Revision 1.34 2004/06/16 20:07:07 florian
  2019. * dwarf branch merged
  2020. Revision 1.33 2004/05/24 17:30:09 peter
  2021. * allow setting of name in dictionary always. Otherwise it is never
  2022. possible to create an item with a name and rename before insert
  2023. this is used in the symtable to hide the current symbol
  2024. Revision 1.32 2004/05/23 14:31:31 peter
  2025. * count fixes for tlinkedlist
  2026. Revision 1.31 2004/04/28 18:02:54 peter
  2027. * add TList to cclasses, remove classes dependency from t_win32
  2028. Revision 1.30.2.3 2004/05/02 14:27:21 peter
  2029. * use sizeof(pointer) instead of 4
  2030. }