cclasses.pas 61 KB

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