cclasses.pas 61 KB

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