cclasses.pas 61 KB

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