cclasses.pas 62 KB

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