cclasses.pas 60 KB

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