cclasses.pas 61 KB

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