cclasses.pas 60 KB

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