cclasses.pas 61 KB

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