cclasses.pas 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385
  1. {
  2. $Id: cclasses.pas,v 1.45 2005/05/12 21:40:42 hajny Exp $
  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 : TFPCHeapStatus;
  332. {$endif HASGETHEAPSTATUS}
  333. begin
  334. {$ifdef HASGETHEAPSTATUS}
  335. status:=GetFPCHeapStatus;
  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 : TFPCHeapStatus;
  345. {$endif HASGETHEAPSTATUS}
  346. begin
  347. {$ifdef HASGETHEAPSTATUS}
  348. if startmem<>0 then
  349. begin
  350. status:=GetFPCHeapStatus;
  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. if NewCapacity > FCapacity then
  418. FillChar (FList^ [FCapacity],
  419. (NewCapacity - FCapacity) * SizeOf (pointer), 0);
  420. FCapacity:=NewCapacity;
  421. end;
  422. procedure TList.SetCount(NewCount: Integer);
  423. begin
  424. If (NewCount<0) or (NewCount>MaxListSize)then
  425. Error(SListCountError,NewCount);
  426. If NewCount<FCount then
  427. FCount:=NewCount
  428. else If NewCount>FCount then
  429. begin
  430. If NewCount>FCapacity then
  431. SetCapacity (NewCount);
  432. If FCount<NewCount then
  433. FillWord (Flist^[FCount],(NewCount-FCount)* WordRatio ,0);
  434. FCount:=Newcount;
  435. end;
  436. end;
  437. destructor TList.Destroy;
  438. begin
  439. Self.Clear;
  440. inherited Destroy;
  441. end;
  442. Function TList.Add(Item: Pointer): Integer;
  443. begin
  444. Self.Insert (Count,Item);
  445. Result:=Count-1;
  446. end;
  447. Procedure TList.Clear;
  448. begin
  449. If Assigned(FList) then
  450. begin
  451. FreeMem (Flist,FCapacity*SizeOf(Pointer));
  452. FList:=Nil;
  453. FCapacity:=0;
  454. FCount:=0;
  455. end;
  456. end;
  457. Procedure TList.Delete(Index: Integer);
  458. begin
  459. If (Index<0) or (Index>=FCount) then
  460. Error (SListIndexError,Index);
  461. FCount:=FCount-1;
  462. System.Move (FList^[Index+1],FList^[Index],(FCount-Index)*SizeOf(Pointer));
  463. // Shrink the list if appropiate
  464. if (FCapacity > 256) and (FCount < FCapacity shr 2) then
  465. begin
  466. FCapacity := FCapacity shr 1;
  467. ReallocMem(FList, SizeOf(Pointer) * FCapacity);
  468. end;
  469. end;
  470. class procedure TList.Error(const Msg: string; Data: Integer);
  471. {$ifdef EXTDEBUG}
  472. var
  473. s : string;
  474. {$endif EXTDEBUG}
  475. begin
  476. {$ifdef EXTDEBUG}
  477. s:=Msg;
  478. Replace(s,'%d',ToStr(Data));
  479. writeln(s);
  480. {$endif EXTDEBUG}
  481. internalerrorproc(200411151);
  482. end;
  483. procedure TList.Exchange(Index1, Index2: Integer);
  484. var Temp : Pointer;
  485. begin
  486. If ((Index1>=FCount) or (Index1<0)) then
  487. Error(SListIndexError,Index1);
  488. If ((Index2>=FCount) or (Index2<0)) then
  489. Error(SListIndexError,Index2);
  490. Temp:=FList^[Index1];
  491. FList^[Index1]:=FList^[Index2];
  492. FList^[Index2]:=Temp;
  493. end;
  494. function TList.Expand: TList;
  495. Var IncSize : Longint;
  496. begin
  497. if FCount<FCapacity then exit;
  498. IncSize:=4;
  499. if FCapacity>3 then IncSize:=IncSize+4;
  500. if FCapacity>8 then IncSize:=IncSize+8;
  501. if FCapacity>127 then Inc(IncSize, FCapacity shr 2);
  502. SetCapacity(FCapacity+IncSize);
  503. Result:=Self;
  504. end;
  505. function TList.First: Pointer;
  506. begin
  507. If FCount=0 then
  508. Result:=Nil
  509. else
  510. Result:=Items[0];
  511. end;
  512. function TList.IndexOf(Item: Pointer): Integer;
  513. begin
  514. Result:=0;
  515. While (Result<FCount) and (Flist^[Result]<>Item) do Result:=Result+1;
  516. If Result=FCount then Result:=-1;
  517. end;
  518. procedure TList.Insert(Index: Integer; Item: Pointer);
  519. begin
  520. If (Index<0) or (Index>FCount )then
  521. Error(SlistIndexError,Index);
  522. IF FCount=FCapacity Then Self.Expand;
  523. If Index<FCount then
  524. System.Move(Flist^[Index],Flist^[Index+1],(FCount-Index)*SizeOf(Pointer));
  525. FList^[Index]:=Item;
  526. FCount:=FCount+1;
  527. end;
  528. function TList.Last: Pointer;
  529. begin
  530. // Wouldn't it be better to return nil if the count is zero ?
  531. If FCount=0 then
  532. Result:=Nil
  533. else
  534. Result:=Items[FCount-1];
  535. end;
  536. procedure TList.Move(CurIndex, NewIndex: Integer);
  537. Var Temp : Pointer;
  538. begin
  539. If ((CurIndex<0) or (CurIndex>Count-1)) then
  540. Error(SListIndexError,CurIndex);
  541. If (NewINdex<0) then
  542. Error(SlistIndexError,NewIndex);
  543. Temp:=FList^[CurIndex];
  544. FList^[CurIndex]:=Nil;
  545. Self.Delete(CurIndex);
  546. // ?? If NewIndex>CurIndex then NewIndex:=NewIndex-1;
  547. // Newindex changes when deleting ??
  548. Self.Insert (NewIndex,Nil);
  549. FList^[NewIndex]:=Temp;
  550. end;
  551. function TList.Remove(Item: Pointer): Integer;
  552. begin
  553. Result:=IndexOf(Item);
  554. If Result<>-1 then
  555. Self.Delete (Result);
  556. end;
  557. Procedure TList.Pack;
  558. Var {Last,I,J,}Runner : Longint;
  559. begin
  560. // Not the fastest; but surely correct
  561. For Runner:=Fcount-1 downto 0 do
  562. if Items[Runner]=Nil then Self.Delete(Runner);
  563. { The following may be faster in case of large and defragmented lists
  564. If count=0 then exit;
  565. Runner:=0;I:=0;
  566. TheLast:=Count;
  567. while runner<count do
  568. begin
  569. // Find first Nil
  570. While (FList^[Runner]<>Nil) and (Runner<Count) do Runner:=Runner+1;
  571. if Runner<Count do
  572. begin
  573. // Start searching for non-nil from last known nil+1
  574. if i<Runner then I:=Runner+1;
  575. While (Flist[I]^=Nil) and (I<Count) do I:=I+1;
  576. // Start looking for last non-nil of block.
  577. J:=I+1;
  578. While (Flist^[J]<>Nil) and (J<Count) do J:=J+1;
  579. // Move block and zero out
  580. Move (Flist^[I],Flist^[Runner],J*SizeOf(Pointer));
  581. FillWord (Flist^[I],(J-I)*WordRatio,0);
  582. // Update Runner and Last to point behind last block
  583. TheLast:=Runner+(J-I);
  584. If J=Count then
  585. begin
  586. // Shortcut, when J=Count we checked all pointers
  587. Runner:=Count
  588. else
  589. begin
  590. Runner:=TheLast;
  591. I:=j;
  592. end;
  593. end;
  594. Count:=TheLast;
  595. }
  596. end;
  597. // Needed by Sort method.
  598. Procedure QuickSort (Flist : PPointerList; L,R : Longint;
  599. Compare : TListSortCompare);
  600. Var I,J : Longint;
  601. P,Q : Pointer;
  602. begin
  603. Repeat
  604. I:=L;
  605. J:=R;
  606. P:=FList^[ (L+R) div 2 ];
  607. repeat
  608. While Compare(P,FList^[i])>0 Do I:=I+1;
  609. While Compare(P,FList^[J])<0 Do J:=J-1;
  610. If I<=J then
  611. begin
  612. Q:=Flist^[I];
  613. Flist^[I]:=FList^[J];
  614. FList^[J]:=Q;
  615. I:=I+1;
  616. J:=j-1;
  617. end;
  618. Until I>J;
  619. If L<J then QuickSort (FList,L,J,Compare);
  620. L:=I;
  621. Until I>=R;
  622. end;
  623. procedure TList.Sort(Compare: TListSortCompare);
  624. begin
  625. If Not Assigned(FList) or (FCount<2) then exit;
  626. QuickSort (Flist, 0, FCount-1,Compare);
  627. end;
  628. procedure TList.Assign(Obj:TList);
  629. // Principle copied from TCollection
  630. var i : Integer;
  631. begin
  632. Clear;
  633. For I:=0 To Obj.Count-1 Do
  634. Add(Obj[i]);
  635. end;
  636. {****************************************************************************
  637. TLinkedListItem
  638. ****************************************************************************}
  639. constructor TLinkedListItem.Create;
  640. begin
  641. Previous:=nil;
  642. Next:=nil;
  643. end;
  644. destructor TLinkedListItem.Destroy;
  645. begin
  646. end;
  647. function TLinkedListItem.GetCopy:TLinkedListItem;
  648. var
  649. p : TLinkedListItem;
  650. l : integer;
  651. begin
  652. p:=TLinkedListItemClass(ClassType).Create;
  653. l:=InstanceSize;
  654. Move(pointer(self)^,pointer(p)^,l);
  655. Result:=p;
  656. end;
  657. {****************************************************************************
  658. TLinkedList
  659. ****************************************************************************}
  660. constructor TLinkedList.Create;
  661. begin
  662. FFirst:=nil;
  663. Flast:=nil;
  664. FCount:=0;
  665. FNoClear:=False;
  666. end;
  667. destructor TLinkedList.destroy;
  668. begin
  669. if not FNoClear then
  670. Clear;
  671. end;
  672. function TLinkedList.empty:boolean;
  673. begin
  674. Empty:=(FFirst=nil);
  675. end;
  676. procedure TLinkedList.Insert(Item:TLinkedListItem);
  677. begin
  678. if FFirst=nil then
  679. begin
  680. FLast:=Item;
  681. Item.Previous:=nil;
  682. Item.Next:=nil;
  683. end
  684. else
  685. begin
  686. FFirst.Previous:=Item;
  687. Item.Previous:=nil;
  688. Item.Next:=FFirst;
  689. end;
  690. FFirst:=Item;
  691. inc(FCount);
  692. end;
  693. procedure TLinkedList.InsertBefore(Item,Loc : TLinkedListItem);
  694. begin
  695. Item.Previous:=Loc.Previous;
  696. Item.Next:=Loc;
  697. Loc.Previous:=Item;
  698. if assigned(Item.Previous) then
  699. Item.Previous.Next:=Item
  700. else
  701. { if we've no next item, we've to adjust FFist }
  702. FFirst:=Item;
  703. inc(FCount);
  704. end;
  705. procedure TLinkedList.InsertAfter(Item,Loc : TLinkedListItem);
  706. begin
  707. Item.Next:=Loc.Next;
  708. Loc.Next:=Item;
  709. Item.Previous:=Loc;
  710. if assigned(Item.Next) then
  711. Item.Next.Previous:=Item
  712. else
  713. { if we've no next item, we've to adjust FLast }
  714. FLast:=Item;
  715. inc(FCount);
  716. end;
  717. procedure TLinkedList.Concat(Item:TLinkedListItem);
  718. begin
  719. if FFirst=nil then
  720. begin
  721. FFirst:=Item;
  722. Item.Previous:=nil;
  723. Item.Next:=nil;
  724. end
  725. else
  726. begin
  727. Flast.Next:=Item;
  728. Item.Previous:=Flast;
  729. Item.Next:=nil;
  730. end;
  731. Flast:=Item;
  732. inc(FCount);
  733. end;
  734. procedure TLinkedList.remove(Item:TLinkedListItem);
  735. begin
  736. if Item=nil then
  737. exit;
  738. if (FFirst=Item) and (Flast=Item) then
  739. begin
  740. FFirst:=nil;
  741. Flast:=nil;
  742. end
  743. else if FFirst=Item then
  744. begin
  745. FFirst:=Item.Next;
  746. if assigned(FFirst) then
  747. FFirst.Previous:=nil;
  748. end
  749. else if Flast=Item then
  750. begin
  751. Flast:=Flast.Previous;
  752. if assigned(Flast) then
  753. Flast.Next:=nil;
  754. end
  755. else
  756. begin
  757. Item.Previous.Next:=Item.Next;
  758. Item.Next.Previous:=Item.Previous;
  759. end;
  760. Item.Next:=nil;
  761. Item.Previous:=nil;
  762. dec(FCount);
  763. end;
  764. procedure TLinkedList.clear;
  765. var
  766. NewNode : TLinkedListItem;
  767. begin
  768. NewNode:=FFirst;
  769. while assigned(NewNode) do
  770. begin
  771. FFirst:=NewNode.Next;
  772. NewNode.Free;
  773. NewNode:=FFirst;
  774. end;
  775. FLast:=nil;
  776. FFirst:=nil;
  777. FCount:=0;
  778. end;
  779. function TLinkedList.GetFirst:TLinkedListItem;
  780. begin
  781. if FFirst=nil then
  782. GetFirst:=nil
  783. else
  784. begin
  785. GetFirst:=FFirst;
  786. if FFirst=FLast then
  787. FLast:=nil;
  788. FFirst:=FFirst.Next;
  789. dec(FCount);
  790. end;
  791. end;
  792. function TLinkedList.GetLast:TLinkedListItem;
  793. begin
  794. if FLast=nil then
  795. Getlast:=nil
  796. else
  797. begin
  798. Getlast:=FLast;
  799. if FLast=FFirst then
  800. FFirst:=nil;
  801. FLast:=FLast.Previous;
  802. dec(FCount);
  803. end;
  804. end;
  805. procedure TLinkedList.insertList(p : TLinkedList);
  806. begin
  807. { empty List ? }
  808. if (p.FFirst=nil) then
  809. exit;
  810. p.Flast.Next:=FFirst;
  811. { we have a double Linked List }
  812. if assigned(FFirst) then
  813. FFirst.Previous:=p.Flast;
  814. FFirst:=p.FFirst;
  815. if (FLast=nil) then
  816. Flast:=p.Flast;
  817. inc(FCount,p.FCount);
  818. { p becomes empty }
  819. p.FFirst:=nil;
  820. p.Flast:=nil;
  821. p.FCount:=0;
  822. end;
  823. procedure TLinkedList.insertListBefore(Item:TLinkedListItem;p : TLinkedList);
  824. begin
  825. { empty List ? }
  826. if (p.FFirst=nil) then
  827. exit;
  828. if (Item=nil) then
  829. begin
  830. { Insert at begin }
  831. InsertList(p);
  832. exit;
  833. end
  834. else
  835. begin
  836. p.FLast.Next:=Item;
  837. p.FFirst.Previous:=Item.Previous;
  838. if assigned(Item.Previous) then
  839. Item.Previous.Next:=p.FFirst
  840. else
  841. FFirst:=p.FFirst;
  842. Item.Previous:=p.FLast;
  843. inc(FCount,p.FCount);
  844. end;
  845. { p becomes empty }
  846. p.FFirst:=nil;
  847. p.Flast:=nil;
  848. p.FCount:=0;
  849. end;
  850. procedure TLinkedList.insertListAfter(Item:TLinkedListItem;p : TLinkedList);
  851. begin
  852. { empty List ? }
  853. if (p.FFirst=nil) then
  854. exit;
  855. if (Item=nil) then
  856. begin
  857. { Insert at begin }
  858. InsertList(p);
  859. exit;
  860. end
  861. else
  862. begin
  863. p.FFirst.Previous:=Item;
  864. p.FLast.Next:=Item.Next;
  865. if assigned(Item.Next) then
  866. Item.Next.Previous:=p.FLast
  867. else
  868. FLast:=p.FLast;
  869. Item.Next:=p.FFirst;
  870. inc(FCount,p.FCount);
  871. end;
  872. { p becomes empty }
  873. p.FFirst:=nil;
  874. p.Flast:=nil;
  875. p.FCount:=0;
  876. end;
  877. procedure TLinkedList.concatList(p : TLinkedList);
  878. begin
  879. if (p.FFirst=nil) then
  880. exit;
  881. if FFirst=nil then
  882. FFirst:=p.FFirst
  883. else
  884. begin
  885. FLast.Next:=p.FFirst;
  886. p.FFirst.Previous:=Flast;
  887. end;
  888. Flast:=p.Flast;
  889. inc(FCount,p.FCount);
  890. { make p empty }
  891. p.Flast:=nil;
  892. p.FFirst:=nil;
  893. p.FCount:=0;
  894. end;
  895. procedure TLinkedList.insertListcopy(p : TLinkedList);
  896. var
  897. NewNode,NewNode2 : TLinkedListItem;
  898. begin
  899. NewNode:=p.First;
  900. while assigned(NewNode) do
  901. begin
  902. NewNode2:=NewNode.Getcopy;
  903. if assigned(NewNode2) then
  904. Insert(NewNode2);
  905. NewNode:=NewNode.Next;
  906. end;
  907. end;
  908. procedure TLinkedList.concatListcopy(p : TLinkedList);
  909. var
  910. NewNode,NewNode2 : TLinkedListItem;
  911. begin
  912. NewNode:=p.First;
  913. while assigned(NewNode) do
  914. begin
  915. NewNode2:=NewNode.Getcopy;
  916. if assigned(NewNode2) then
  917. Concat(NewNode2);
  918. NewNode:=NewNode.Next;
  919. end;
  920. end;
  921. {****************************************************************************
  922. TStringListItem
  923. ****************************************************************************}
  924. constructor TStringListItem.Create(const s:string);
  925. begin
  926. inherited Create;
  927. FPStr:=stringdup(s);
  928. end;
  929. destructor TStringListItem.Destroy;
  930. begin
  931. stringdispose(FPStr);
  932. end;
  933. function TStringListItem.Str:string;
  934. begin
  935. Str:=FPStr^;
  936. end;
  937. function TStringListItem.GetCopy:TLinkedListItem;
  938. begin
  939. Result:=(inherited GetCopy);
  940. TStringListItem(Result).FPStr:=stringdup(FPstr^);
  941. end;
  942. {****************************************************************************
  943. TSTRINGList
  944. ****************************************************************************}
  945. constructor tstringList.Create;
  946. begin
  947. inherited Create;
  948. FDoubles:=true;
  949. end;
  950. constructor tstringList.Create_no_double;
  951. begin
  952. inherited Create;
  953. FDoubles:=false;
  954. end;
  955. procedure tstringList.insert(const s : string);
  956. begin
  957. if (s='') or
  958. ((not FDoubles) and (find(s)<>nil)) then
  959. exit;
  960. inherited insert(tstringListItem.create(s));
  961. end;
  962. procedure tstringList.concat(const s : string);
  963. begin
  964. if (s='') or
  965. ((not FDoubles) and (find(s)<>nil)) then
  966. exit;
  967. inherited concat(tstringListItem.create(s));
  968. end;
  969. procedure tstringList.remove(const s : string);
  970. var
  971. p : tstringListItem;
  972. begin
  973. if s='' then
  974. exit;
  975. p:=find(s);
  976. if assigned(p) then
  977. begin
  978. inherited Remove(p);
  979. p.Free;
  980. end;
  981. end;
  982. function tstringList.GetFirst : string;
  983. var
  984. p : tstringListItem;
  985. begin
  986. p:=tstringListItem(inherited GetFirst);
  987. if p=nil then
  988. GetFirst:=''
  989. else
  990. begin
  991. GetFirst:=p.FPStr^;
  992. p.free;
  993. end;
  994. end;
  995. function tstringList.Getlast : string;
  996. var
  997. p : tstringListItem;
  998. begin
  999. p:=tstringListItem(inherited Getlast);
  1000. if p=nil then
  1001. Getlast:=''
  1002. else
  1003. begin
  1004. Getlast:=p.FPStr^;
  1005. p.free;
  1006. end;
  1007. end;
  1008. function tstringList.FindCase(const s:string):TstringListItem;
  1009. var
  1010. NewNode : tstringListItem;
  1011. begin
  1012. result:=nil;
  1013. if s='' then
  1014. exit;
  1015. NewNode:=tstringListItem(FFirst);
  1016. while assigned(NewNode) do
  1017. begin
  1018. if NewNode.FPStr^=s then
  1019. begin
  1020. result:=NewNode;
  1021. exit;
  1022. end;
  1023. NewNode:=tstringListItem(NewNode.Next);
  1024. end;
  1025. end;
  1026. function tstringList.Find(const s:string):TstringListItem;
  1027. var
  1028. NewNode : tstringListItem;
  1029. ups : string;
  1030. begin
  1031. result:=nil;
  1032. if s='' then
  1033. exit;
  1034. ups:=upper(s);
  1035. NewNode:=tstringListItem(FFirst);
  1036. while assigned(NewNode) do
  1037. begin
  1038. if upper(NewNode.FPStr^)=ups then
  1039. begin
  1040. result:=NewNode;
  1041. exit;
  1042. end;
  1043. NewNode:=tstringListItem(NewNode.Next);
  1044. end;
  1045. end;
  1046. procedure TStringList.InsertItem(item:TStringListItem);
  1047. begin
  1048. inherited Insert(item);
  1049. end;
  1050. procedure TStringList.ConcatItem(item:TStringListItem);
  1051. begin
  1052. inherited Concat(item);
  1053. end;
  1054. {****************************************************************************
  1055. TNamedIndexItem
  1056. ****************************************************************************}
  1057. constructor TNamedIndexItem.Create;
  1058. begin
  1059. { index }
  1060. Findexnr:=-1;
  1061. FindexNext:=nil;
  1062. { dictionary }
  1063. Fleft:=nil;
  1064. Fright:=nil;
  1065. FName:=nil;
  1066. Fspeedvalue:=cardinal($ffffffff);
  1067. { List }
  1068. FListNext:=nil;
  1069. end;
  1070. constructor TNamedIndexItem.Createname(const n:string);
  1071. begin
  1072. { index }
  1073. Findexnr:=-1;
  1074. FindexNext:=nil;
  1075. { dictionary }
  1076. Fleft:=nil;
  1077. Fright:=nil;
  1078. fspeedvalue:=getspeedvalue(n);
  1079. {$ifdef compress}
  1080. FName:=stringdup(minilzw_encode(n));
  1081. {$else}
  1082. FName:=stringdup(n);
  1083. {$endif}
  1084. { List }
  1085. FListNext:=nil;
  1086. end;
  1087. destructor TNamedIndexItem.destroy;
  1088. begin
  1089. stringdispose(FName);
  1090. end;
  1091. procedure TNamedIndexItem.setname(const n:string);
  1092. begin
  1093. if assigned(FName) then
  1094. stringdispose(FName);
  1095. fspeedvalue:=getspeedvalue(n);
  1096. {$ifdef compress}
  1097. FName:=stringdup(minilzw_encode(n));
  1098. {$else}
  1099. FName:=stringdup(n);
  1100. {$endif}
  1101. end;
  1102. function TNamedIndexItem.GetName:string;
  1103. begin
  1104. if assigned(FName) then
  1105. {$ifdef compress}
  1106. Getname:=minilzw_decode(FName^)
  1107. {$else}
  1108. Getname:=FName^
  1109. {$endif}
  1110. else
  1111. Getname:='';
  1112. end;
  1113. {****************************************************************************
  1114. TDICTIONARY
  1115. ****************************************************************************}
  1116. constructor Tdictionary.Create;
  1117. begin
  1118. FRoot:=nil;
  1119. FHashArray:=nil;
  1120. noclear:=false;
  1121. delete_doubles:=false;
  1122. end;
  1123. procedure Tdictionary.usehash;
  1124. begin
  1125. if not(assigned(FRoot)) and
  1126. not(assigned(FHashArray)) then
  1127. begin
  1128. New(FHashArray);
  1129. fillchar(FHashArray^,sizeof(FHashArray^),0);
  1130. end;
  1131. end;
  1132. function counttree(p: tnamedindexitem): longint;
  1133. begin
  1134. counttree:=0;
  1135. if not assigned(p) then
  1136. exit;
  1137. result := 1;
  1138. inc(result,counttree(p.fleft));
  1139. inc(result,counttree(p.fright));
  1140. end;
  1141. destructor Tdictionary.destroy;
  1142. begin
  1143. if not noclear then
  1144. clear;
  1145. if assigned(FHashArray) then
  1146. begin
  1147. dispose(FHashArray);
  1148. end;
  1149. end;
  1150. procedure Tdictionary.cleartree(var obj:TNamedIndexItem);
  1151. begin
  1152. if assigned(obj.Fleft) then
  1153. cleartree(obj.FLeft);
  1154. if assigned(obj.FRight) then
  1155. cleartree(obj.FRight);
  1156. obj.free;
  1157. obj:=nil;
  1158. end;
  1159. procedure Tdictionary.clear;
  1160. var
  1161. w : integer;
  1162. begin
  1163. if assigned(FRoot) then
  1164. cleartree(FRoot);
  1165. if assigned(FHashArray) then
  1166. for w:= low(FHashArray^) to high(FHashArray^) do
  1167. if assigned(FHashArray^[w]) then
  1168. cleartree(FHashArray^[w]);
  1169. end;
  1170. function Tdictionary.delete(const s:string):TNamedIndexItem;
  1171. var
  1172. p,SpeedValue : cardinal;
  1173. n : TNamedIndexItem;
  1174. {$ifdef compress}
  1175. senc:string;
  1176. {$else}
  1177. senc:string absolute s;
  1178. {$endif}
  1179. procedure insert_right_bottom(var root,Atree:TNamedIndexItem);
  1180. begin
  1181. while root.FRight<>nil do
  1182. root:=root.FRight;
  1183. root.FRight:=Atree;
  1184. end;
  1185. function delete_from_tree(root:TNamedIndexItem):TNamedIndexItem;
  1186. type
  1187. leftright=(left,right);
  1188. var
  1189. lr : leftright;
  1190. oldroot : TNamedIndexItem;
  1191. begin
  1192. oldroot:=nil;
  1193. while (root<>nil) and (root.SpeedValue<>SpeedValue) do
  1194. begin
  1195. oldroot:=root;
  1196. if SpeedValue<root.SpeedValue then
  1197. begin
  1198. root:=root.FRight;
  1199. lr:=right;
  1200. end
  1201. else
  1202. begin
  1203. root:=root.FLeft;
  1204. lr:=left;
  1205. end;
  1206. end;
  1207. while (root<>nil) and (root.FName^<>senc) do
  1208. begin
  1209. oldroot:=root;
  1210. if senc<root.FName^ then
  1211. begin
  1212. root:=root.FRight;
  1213. lr:=right;
  1214. end
  1215. else
  1216. begin
  1217. root:=root.FLeft;
  1218. lr:=left;
  1219. end;
  1220. end;
  1221. if root<>nil then
  1222. begin
  1223. dec(FCount);
  1224. if root.FLeft<>nil then
  1225. begin
  1226. { Now the Node pointing to root must point to the left
  1227. subtree of root. The right subtree of root must be
  1228. connected to the right bottom of the left subtree.}
  1229. if lr=left then
  1230. oldroot.FLeft:=root.FLeft
  1231. else
  1232. oldroot.FRight:=root.FLeft;
  1233. if root.FRight<>nil then
  1234. insert_right_bottom(root.FLeft,root.FRight);
  1235. end
  1236. else
  1237. begin
  1238. { There is no left subtree. So we can just replace the Node to
  1239. delete with the right subtree.}
  1240. if lr=left then
  1241. oldroot.FLeft:=root.FRight
  1242. else
  1243. oldroot.FRight:=root.FRight;
  1244. end;
  1245. end;
  1246. delete_from_tree:=root;
  1247. end;
  1248. begin
  1249. {$ifdef compress}
  1250. senc:=minilzw_encode(s);
  1251. {$endif}
  1252. SpeedValue:=GetSpeedValue(s);
  1253. n:=FRoot;
  1254. if assigned(FHashArray) then
  1255. begin
  1256. { First, check if the Node to delete directly located under
  1257. the hasharray.}
  1258. p:=SpeedValue mod hasharraysize;
  1259. n:=FHashArray^[p];
  1260. if (n<>nil) and (n.SpeedValue=SpeedValue) and
  1261. (n.FName^=senc) then
  1262. begin
  1263. { The Node to delete is directly located under the
  1264. hasharray. Make the hasharray point to the left
  1265. subtree of the Node and place the right subtree on
  1266. the right-bottom of the left subtree.}
  1267. if n.FLeft<>nil then
  1268. begin
  1269. FHashArray^[p]:=n.FLeft;
  1270. if n.FRight<>nil then
  1271. insert_right_bottom(n.FLeft,n.FRight);
  1272. end
  1273. else
  1274. FHashArray^[p]:=n.FRight;
  1275. delete:=n;
  1276. dec(FCount);
  1277. exit;
  1278. end;
  1279. end
  1280. else
  1281. begin
  1282. { First check if the Node to delete is the root.}
  1283. if (FRoot<>nil) and (n.SpeedValue=SpeedValue) and
  1284. (n.FName^=senc) then
  1285. begin
  1286. if n.FLeft<>nil then
  1287. begin
  1288. FRoot:=n.FLeft;
  1289. if n.FRight<>nil then
  1290. insert_right_bottom(n.FLeft,n.FRight);
  1291. end
  1292. else
  1293. FRoot:=n.FRight;
  1294. delete:=n;
  1295. dec(FCount);
  1296. exit;
  1297. end;
  1298. end;
  1299. delete:=delete_from_tree(n);
  1300. end;
  1301. function Tdictionary.empty:boolean;
  1302. var
  1303. w : integer;
  1304. begin
  1305. if assigned(FHashArray) then
  1306. begin
  1307. empty:=false;
  1308. for w:=low(FHashArray^) to high(FHashArray^) do
  1309. if assigned(FHashArray^[w]) then
  1310. exit;
  1311. empty:=true;
  1312. end
  1313. else
  1314. empty:=(FRoot=nil);
  1315. end;
  1316. procedure Tdictionary.foreach(proc2call:TNamedIndexcallback;arg:pointer);
  1317. procedure a(p:TNamedIndexItem;arg:pointer);
  1318. begin
  1319. proc2call(p,arg);
  1320. if assigned(p.FLeft) then
  1321. a(p.FLeft,arg);
  1322. if assigned(p.FRight) then
  1323. a(p.FRight,arg);
  1324. end;
  1325. var
  1326. i : integer;
  1327. begin
  1328. if assigned(FHashArray) then
  1329. begin
  1330. for i:=low(FHashArray^) to high(FHashArray^) do
  1331. if assigned(FHashArray^[i]) then
  1332. a(FHashArray^[i],arg);
  1333. end
  1334. else
  1335. if assigned(FRoot) then
  1336. a(FRoot,arg);
  1337. end;
  1338. procedure Tdictionary.foreach_static(proc2call:TNamedIndexStaticCallback;arg:pointer);
  1339. procedure a(p:TNamedIndexItem;arg:pointer);
  1340. begin
  1341. proc2call(p,arg);
  1342. if assigned(p.FLeft) then
  1343. a(p.FLeft,arg);
  1344. if assigned(p.FRight) then
  1345. a(p.FRight,arg);
  1346. end;
  1347. var
  1348. i : integer;
  1349. begin
  1350. if assigned(FHashArray) then
  1351. begin
  1352. for i:=low(FHashArray^) to high(FHashArray^) do
  1353. if assigned(FHashArray^[i]) then
  1354. a(FHashArray^[i],arg);
  1355. end
  1356. else
  1357. if assigned(FRoot) then
  1358. a(FRoot,arg);
  1359. end;
  1360. function Tdictionary.replace(oldobj,newobj:TNamedIndexItem):boolean;
  1361. var
  1362. hp : TNamedIndexItem;
  1363. begin
  1364. hp:=nil;
  1365. Replace:=false;
  1366. { must be the same name and hash }
  1367. if (oldobj.FSpeedValue<>newobj.FSpeedValue) or
  1368. (oldobj.FName^<>newobj.FName^) then
  1369. exit;
  1370. { copy tree info }
  1371. newobj.FLeft:=oldobj.FLeft;
  1372. newobj.FRight:=oldobj.FRight;
  1373. { update treeroot }
  1374. if assigned(FHashArray) then
  1375. begin
  1376. hp:=FHashArray^[newobj.FSpeedValue mod hasharraysize];
  1377. if hp=oldobj then
  1378. begin
  1379. FHashArray^[newobj.FSpeedValue mod hasharraysize]:=newobj;
  1380. hp:=nil;
  1381. end;
  1382. end
  1383. else
  1384. begin
  1385. hp:=FRoot;
  1386. if hp=oldobj then
  1387. begin
  1388. FRoot:=newobj;
  1389. hp:=nil;
  1390. end;
  1391. end;
  1392. { update parent entry }
  1393. while assigned(hp) do
  1394. begin
  1395. { is the node to replace the left or right, then
  1396. update this node and stop }
  1397. if hp.FLeft=oldobj then
  1398. begin
  1399. hp.FLeft:=newobj;
  1400. break;
  1401. end;
  1402. if hp.FRight=oldobj then
  1403. begin
  1404. hp.FRight:=newobj;
  1405. break;
  1406. end;
  1407. { First check SpeedValue, to allow a fast insert }
  1408. if hp.SpeedValue>oldobj.SpeedValue then
  1409. hp:=hp.FRight
  1410. else
  1411. if hp.SpeedValue<oldobj.SpeedValue then
  1412. hp:=hp.FLeft
  1413. else
  1414. begin
  1415. if (hp.FName^=oldobj.FName^) then
  1416. begin
  1417. { this can never happend, return error }
  1418. exit;
  1419. end
  1420. else
  1421. if oldobj.FName^>hp.FName^ then
  1422. hp:=hp.FLeft
  1423. else
  1424. hp:=hp.FRight;
  1425. end;
  1426. end;
  1427. Replace:=true;
  1428. end;
  1429. function Tdictionary.insert(obj:TNamedIndexItem):TNamedIndexItem;
  1430. begin
  1431. inc(FCount);
  1432. if assigned(FHashArray) then
  1433. insert:=insertNode(obj,FHashArray^[obj.SpeedValue mod hasharraysize])
  1434. else
  1435. insert:=insertNode(obj,FRoot);
  1436. end;
  1437. function tdictionary.insertNode(NewNode:TNamedIndexItem;var currNode:TNamedIndexItem):TNamedIndexItem;
  1438. begin
  1439. if currNode=nil then
  1440. begin
  1441. currNode:=NewNode;
  1442. insertNode:=NewNode;
  1443. end
  1444. { First check SpeedValue, to allow a fast insert }
  1445. else
  1446. if currNode.SpeedValue>NewNode.SpeedValue then
  1447. insertNode:=insertNode(NewNode,currNode.FRight)
  1448. else
  1449. if currNode.SpeedValue<NewNode.SpeedValue then
  1450. insertNode:=insertNode(NewNode,currNode.FLeft)
  1451. else
  1452. begin
  1453. if currNode.FName^>NewNode.FName^ then
  1454. insertNode:=insertNode(NewNode,currNode.FRight)
  1455. else
  1456. if currNode.FName^<NewNode.FName^ then
  1457. insertNode:=insertNode(NewNode,currNode.FLeft)
  1458. else
  1459. begin
  1460. if (delete_doubles) and
  1461. assigned(currNode) then
  1462. begin
  1463. NewNode.FLeft:=currNode.FLeft;
  1464. NewNode.FRight:=currNode.FRight;
  1465. if delete_doubles then
  1466. begin
  1467. currnode.FLeft:=nil;
  1468. currnode.FRight:=nil;
  1469. currnode.free;
  1470. end;
  1471. currNode:=NewNode;
  1472. insertNode:=NewNode;
  1473. end
  1474. else
  1475. insertNode:=currNode;
  1476. end;
  1477. end;
  1478. end;
  1479. procedure tdictionary.inserttree(currtree,currroot:TNamedIndexItem);
  1480. begin
  1481. if assigned(currtree) then
  1482. begin
  1483. inserttree(currtree.FLeft,currroot);
  1484. inserttree(currtree.FRight,currroot);
  1485. currtree.FRight:=nil;
  1486. currtree.FLeft:=nil;
  1487. insertNode(currtree,currroot);
  1488. end;
  1489. end;
  1490. function tdictionary.rename(const olds,News : string):TNamedIndexItem;
  1491. var
  1492. spdval : cardinal;
  1493. lasthp,
  1494. hp,hp2,hp3 : TNamedIndexItem;
  1495. {$ifdef compress}
  1496. oldsenc,newsenc:string;
  1497. {$else}
  1498. oldsenc:string absolute olds;
  1499. newsenc:string absolute news;
  1500. {$endif}
  1501. begin
  1502. {$ifdef compress}
  1503. oldsenc:=minilzw_encode(olds);
  1504. newsenc:=minilzw_encode(news);
  1505. {$endif}
  1506. spdval:=GetSpeedValue(olds);
  1507. if assigned(FHashArray) then
  1508. hp:=FHashArray^[spdval mod hasharraysize]
  1509. else
  1510. hp:=FRoot;
  1511. lasthp:=nil;
  1512. while assigned(hp) do
  1513. begin
  1514. if spdval>hp.SpeedValue then
  1515. begin
  1516. lasthp:=hp;
  1517. hp:=hp.FLeft
  1518. end
  1519. else
  1520. if spdval<hp.SpeedValue then
  1521. begin
  1522. lasthp:=hp;
  1523. hp:=hp.FRight
  1524. end
  1525. else
  1526. begin
  1527. if (hp.FName^=oldsenc) then
  1528. begin
  1529. { Get in hp2 the replacer for the root or hasharr }
  1530. hp2:=hp.FLeft;
  1531. hp3:=hp.FRight;
  1532. if not assigned(hp2) then
  1533. begin
  1534. hp2:=hp.FRight;
  1535. hp3:=hp.FLeft;
  1536. end;
  1537. { remove entry from the tree }
  1538. if assigned(lasthp) then
  1539. begin
  1540. if lasthp.FLeft=hp then
  1541. lasthp.FLeft:=hp2
  1542. else
  1543. lasthp.FRight:=hp2;
  1544. end
  1545. else
  1546. begin
  1547. if assigned(FHashArray) then
  1548. FHashArray^[spdval mod hasharraysize]:=hp2
  1549. else
  1550. FRoot:=hp2;
  1551. end;
  1552. { reinsert the hp3 in the tree from hp2 }
  1553. inserttree(hp3,hp2);
  1554. { reset Node with New values }
  1555. hp.FLeft:=nil;
  1556. hp.FRight:=nil;
  1557. stringdispose(hp.FName);
  1558. hp.FName:=stringdup(newsenc);
  1559. hp.FSpeedValue:=GetSpeedValue(news);
  1560. { reinsert }
  1561. if assigned(FHashArray) then
  1562. rename:=insertNode(hp,FHashArray^[hp.SpeedValue mod hasharraysize])
  1563. else
  1564. rename:=insertNode(hp,FRoot);
  1565. exit;
  1566. end
  1567. else
  1568. if oldsenc>hp.FName^ then
  1569. begin
  1570. lasthp:=hp;
  1571. hp:=hp.FLeft
  1572. end
  1573. else
  1574. begin
  1575. lasthp:=hp;
  1576. hp:=hp.FRight;
  1577. end;
  1578. end;
  1579. end;
  1580. result := nil;
  1581. end;
  1582. function Tdictionary.search(const s:string):TNamedIndexItem;
  1583. begin
  1584. search:=speedsearch(s,getspeedvalue(s));
  1585. end;
  1586. function Tdictionary.speedsearch(const s:string;SpeedValue:cardinal):TNamedIndexItem;
  1587. var
  1588. NewNode:TNamedIndexItem;
  1589. {$ifdef compress}
  1590. decn:string;
  1591. {$endif}
  1592. begin
  1593. if assigned(FHashArray) then
  1594. NewNode:=FHashArray^[SpeedValue mod hasharraysize]
  1595. else
  1596. NewNode:=FRoot;
  1597. while assigned(NewNode) do
  1598. begin
  1599. if SpeedValue>NewNode.SpeedValue then
  1600. NewNode:=NewNode.FLeft
  1601. else
  1602. if SpeedValue<NewNode.SpeedValue then
  1603. NewNode:=NewNode.FRight
  1604. else
  1605. begin
  1606. {$ifdef compress}
  1607. decn:=minilzw_decode(newnode.fname^);
  1608. if (decn=s) then
  1609. begin
  1610. speedsearch:=NewNode;
  1611. exit;
  1612. end
  1613. else
  1614. if s>decn then
  1615. NewNode:=NewNode.FLeft
  1616. else
  1617. NewNode:=NewNode.FRight;
  1618. {$else}
  1619. if (NewNode.FName^=s) then
  1620. begin
  1621. speedsearch:=NewNode;
  1622. exit;
  1623. end
  1624. else
  1625. if s>NewNode.FName^ then
  1626. NewNode:=NewNode.FLeft
  1627. else
  1628. NewNode:=NewNode.FRight;
  1629. {$endif}
  1630. end;
  1631. end;
  1632. speedsearch:=nil;
  1633. end;
  1634. {****************************************************************************
  1635. tsingleList
  1636. ****************************************************************************}
  1637. constructor tsingleList.create;
  1638. begin
  1639. First:=nil;
  1640. last:=nil;
  1641. end;
  1642. procedure tsingleList.reset;
  1643. begin
  1644. First:=nil;
  1645. last:=nil;
  1646. end;
  1647. procedure tsingleList.clear;
  1648. var
  1649. hp,hp2 : TNamedIndexItem;
  1650. begin
  1651. hp:=First;
  1652. while assigned(hp) do
  1653. begin
  1654. hp2:=hp;
  1655. hp:=hp.FListNext;
  1656. hp2.free;
  1657. end;
  1658. First:=nil;
  1659. last:=nil;
  1660. end;
  1661. procedure tsingleList.insert(p:TNamedIndexItem);
  1662. begin
  1663. if not assigned(First) then
  1664. First:=p
  1665. else
  1666. last.FListNext:=p;
  1667. last:=p;
  1668. p.FListNext:=nil;
  1669. end;
  1670. {****************************************************************************
  1671. tindexarray
  1672. ****************************************************************************}
  1673. constructor tindexarray.create(Agrowsize:integer);
  1674. begin
  1675. growsize:=Agrowsize;
  1676. size:=0;
  1677. count:=0;
  1678. data:=nil;
  1679. First:=nil;
  1680. noclear:=false;
  1681. end;
  1682. destructor tindexarray.destroy;
  1683. begin
  1684. if assigned(data) then
  1685. begin
  1686. if not noclear then
  1687. clear;
  1688. freemem(data);
  1689. data:=nil;
  1690. end;
  1691. end;
  1692. function tindexarray.search(nr:integer):TNamedIndexItem;
  1693. begin
  1694. if nr<=count then
  1695. search:=data^[nr]
  1696. else
  1697. search:=nil;
  1698. end;
  1699. procedure tindexarray.clear;
  1700. var
  1701. i : integer;
  1702. begin
  1703. for i:=1 to count do
  1704. if assigned(data^[i]) then
  1705. begin
  1706. data^[i].free;
  1707. data^[i]:=nil;
  1708. end;
  1709. count:=0;
  1710. First:=nil;
  1711. end;
  1712. procedure tindexarray.foreach(proc2call : Tnamedindexcallback;arg:pointer);
  1713. var
  1714. i : integer;
  1715. begin
  1716. for i:=1 to count do
  1717. if assigned(data^[i]) then
  1718. proc2call(data^[i],arg);
  1719. end;
  1720. procedure tindexarray.foreach_static(proc2call : Tnamedindexstaticcallback;arg:pointer);
  1721. var
  1722. i : integer;
  1723. begin
  1724. for i:=1 to count do
  1725. if assigned(data^[i]) then
  1726. proc2call(data^[i],arg);
  1727. end;
  1728. procedure tindexarray.grow(gsize:integer);
  1729. var
  1730. osize : integer;
  1731. begin
  1732. osize:=size;
  1733. inc(size,gsize);
  1734. reallocmem(data,size*sizeof(pointer));
  1735. fillchar(data^[osize+1],gsize*sizeof(pointer),0);
  1736. end;
  1737. procedure tindexarray.deleteindex(p:TNamedIndexItem);
  1738. var
  1739. i : integer;
  1740. begin
  1741. i:=p.Findexnr;
  1742. { update counter }
  1743. if i=count then
  1744. dec(count);
  1745. { update Linked List }
  1746. while (i>0) do
  1747. begin
  1748. dec(i);
  1749. if (i>0) and assigned(data^[i]) then
  1750. begin
  1751. data^[i].FindexNext:=data^[p.Findexnr].FindexNext;
  1752. break;
  1753. end;
  1754. end;
  1755. if i=0 then
  1756. First:=p.FindexNext;
  1757. data^[p.FIndexnr]:=nil;
  1758. { clear entry }
  1759. p.FIndexnr:=-1;
  1760. p.FIndexNext:=nil;
  1761. end;
  1762. procedure tindexarray.delete(var p:TNamedIndexItem);
  1763. begin
  1764. deleteindex(p);
  1765. p.free;
  1766. p:=nil;
  1767. end;
  1768. procedure tindexarray.insert(p:TNamedIndexItem);
  1769. var
  1770. i : integer;
  1771. begin
  1772. if p.FIndexnr=-1 then
  1773. begin
  1774. inc(count);
  1775. p.FIndexnr:=count;
  1776. end;
  1777. if p.FIndexnr>count then
  1778. count:=p.FIndexnr;
  1779. if count>size then
  1780. grow(((count div growsize)+1)*growsize);
  1781. Assert(not assigned(data^[p.FIndexnr]) or (p=data^[p.FIndexnr]));
  1782. data^[p.FIndexnr]:=p;
  1783. { update Linked List backward }
  1784. i:=p.FIndexnr;
  1785. while (i>0) do
  1786. begin
  1787. dec(i);
  1788. if (i>0) and assigned(data^[i]) then
  1789. begin
  1790. data^[i].FIndexNext:=p;
  1791. break;
  1792. end;
  1793. end;
  1794. if i=0 then
  1795. First:=p;
  1796. { update Linked List forward }
  1797. i:=p.FIndexnr;
  1798. while (i<=count) do
  1799. begin
  1800. inc(i);
  1801. if (i<=count) and assigned(data^[i]) then
  1802. begin
  1803. p.FIndexNext:=data^[i];
  1804. exit;
  1805. end;
  1806. end;
  1807. if i>count then
  1808. p.FIndexNext:=nil;
  1809. end;
  1810. procedure tindexarray.replace(oldp,newp:TNamedIndexItem);
  1811. var
  1812. i : integer;
  1813. begin
  1814. newp.FIndexnr:=oldp.FIndexnr;
  1815. newp.FIndexNext:=oldp.FIndexNext;
  1816. data^[newp.FIndexnr]:=newp;
  1817. if First=oldp then
  1818. First:=newp;
  1819. { update Linked List backward }
  1820. i:=newp.FIndexnr;
  1821. while (i>0) do
  1822. begin
  1823. dec(i);
  1824. if (i>0) and assigned(data^[i]) then
  1825. begin
  1826. data^[i].FIndexNext:=newp;
  1827. break;
  1828. end;
  1829. end;
  1830. end;
  1831. {****************************************************************************
  1832. tdynamicarray
  1833. ****************************************************************************}
  1834. constructor tdynamicarray.create(Ablocksize:integer);
  1835. begin
  1836. FPosn:=0;
  1837. FPosnblock:=nil;
  1838. FFirstblock:=nil;
  1839. FLastblock:=nil;
  1840. Fblocksize:=Ablocksize;
  1841. grow;
  1842. end;
  1843. destructor tdynamicarray.destroy;
  1844. var
  1845. hp : pdynamicblock;
  1846. begin
  1847. while assigned(FFirstblock) do
  1848. begin
  1849. hp:=FFirstblock;
  1850. FFirstblock:=FFirstblock^.Next;
  1851. Freemem(hp);
  1852. end;
  1853. end;
  1854. function tdynamicarray.size:integer;
  1855. begin
  1856. if assigned(FLastblock) then
  1857. size:=FLastblock^.pos+FLastblock^.used
  1858. else
  1859. size:=0;
  1860. end;
  1861. procedure tdynamicarray.reset;
  1862. var
  1863. hp : pdynamicblock;
  1864. begin
  1865. while assigned(FFirstblock) do
  1866. begin
  1867. hp:=FFirstblock;
  1868. FFirstblock:=FFirstblock^.Next;
  1869. Freemem(hp);
  1870. end;
  1871. FPosn:=0;
  1872. FPosnblock:=nil;
  1873. FFirstblock:=nil;
  1874. FLastblock:=nil;
  1875. grow;
  1876. end;
  1877. procedure tdynamicarray.grow;
  1878. var
  1879. nblock : pdynamicblock;
  1880. begin
  1881. Getmem(nblock,blocksize+dynamicblockbasesize);
  1882. if not assigned(FFirstblock) then
  1883. begin
  1884. FFirstblock:=nblock;
  1885. FPosnblock:=nblock;
  1886. nblock^.pos:=0;
  1887. end
  1888. else
  1889. begin
  1890. FLastblock^.Next:=nblock;
  1891. nblock^.pos:=FLastblock^.pos+FLastblock^.used;
  1892. end;
  1893. nblock^.used:=0;
  1894. nblock^.Next:=nil;
  1895. fillchar(nblock^.data,blocksize,0);
  1896. FLastblock:=nblock;
  1897. end;
  1898. procedure tdynamicarray.align(i:integer);
  1899. var
  1900. j : integer;
  1901. begin
  1902. j:=(FPosn mod i);
  1903. if j<>0 then
  1904. begin
  1905. j:=i-j;
  1906. if FPosnblock^.used+j>blocksize then
  1907. begin
  1908. dec(j,blocksize-FPosnblock^.used);
  1909. FPosnblock^.used:=blocksize;
  1910. grow;
  1911. FPosnblock:=FLastblock;
  1912. end;
  1913. inc(FPosnblock^.used,j);
  1914. inc(FPosn,j);
  1915. end;
  1916. end;
  1917. procedure tdynamicarray.seek(i:integer);
  1918. begin
  1919. if (i<FPosnblock^.pos) or (i>=FPosnblock^.pos+blocksize) then
  1920. begin
  1921. { set FPosnblock correct if the size is bigger then
  1922. the current block }
  1923. if FPosnblock^.pos>i then
  1924. FPosnblock:=FFirstblock;
  1925. while assigned(FPosnblock) do
  1926. begin
  1927. if FPosnblock^.pos+blocksize>i then
  1928. break;
  1929. FPosnblock:=FPosnblock^.Next;
  1930. end;
  1931. { not found ? then increase blocks }
  1932. if not assigned(FPosnblock) then
  1933. begin
  1934. repeat
  1935. { the current FLastblock is now also fully used }
  1936. FLastblock^.used:=blocksize;
  1937. grow;
  1938. FPosnblock:=FLastblock;
  1939. until FPosnblock^.pos+blocksize>=i;
  1940. end;
  1941. end;
  1942. FPosn:=i;
  1943. if FPosn mod blocksize>FPosnblock^.used then
  1944. FPosnblock^.used:=FPosn mod blocksize;
  1945. end;
  1946. procedure tdynamicarray.write(const d;len:integer);
  1947. var
  1948. p : pchar;
  1949. i,j : integer;
  1950. begin
  1951. p:=pchar(@d);
  1952. while (len>0) do
  1953. begin
  1954. i:=FPosn mod blocksize;
  1955. if i+len>=blocksize then
  1956. begin
  1957. j:=blocksize-i;
  1958. move(p^,FPosnblock^.data[i],j);
  1959. inc(p,j);
  1960. inc(FPosn,j);
  1961. dec(len,j);
  1962. FPosnblock^.used:=blocksize;
  1963. if assigned(FPosnblock^.Next) then
  1964. FPosnblock:=FPosnblock^.Next
  1965. else
  1966. begin
  1967. grow;
  1968. FPosnblock:=FLastblock;
  1969. end;
  1970. end
  1971. else
  1972. begin
  1973. move(p^,FPosnblock^.data[i],len);
  1974. inc(p,len);
  1975. inc(FPosn,len);
  1976. i:=FPosn mod blocksize;
  1977. if i>FPosnblock^.used then
  1978. FPosnblock^.used:=i;
  1979. len:=0;
  1980. end;
  1981. end;
  1982. end;
  1983. procedure tdynamicarray.writestr(const s:string);
  1984. begin
  1985. write(s[1],length(s));
  1986. end;
  1987. function tdynamicarray.read(var d;len:integer):integer;
  1988. var
  1989. p : pchar;
  1990. i,j,res : integer;
  1991. begin
  1992. res:=0;
  1993. p:=pchar(@d);
  1994. while (len>0) do
  1995. begin
  1996. i:=FPosn mod blocksize;
  1997. if i+len>=FPosnblock^.used then
  1998. begin
  1999. j:=FPosnblock^.used-i;
  2000. move(FPosnblock^.data[i],p^,j);
  2001. inc(p,j);
  2002. inc(FPosn,j);
  2003. inc(res,j);
  2004. dec(len,j);
  2005. if assigned(FPosnblock^.Next) then
  2006. FPosnblock:=FPosnblock^.Next
  2007. else
  2008. break;
  2009. end
  2010. else
  2011. begin
  2012. move(FPosnblock^.data[i],p^,len);
  2013. inc(p,len);
  2014. inc(FPosn,len);
  2015. inc(res,len);
  2016. len:=0;
  2017. end;
  2018. end;
  2019. read:=res;
  2020. end;
  2021. procedure tdynamicarray.readstream(f:TCStream;maxlen:longint);
  2022. var
  2023. i,left : integer;
  2024. begin
  2025. if maxlen=-1 then
  2026. maxlen:=maxlongint;
  2027. repeat
  2028. left:=blocksize-FPosnblock^.used;
  2029. if left>maxlen then
  2030. left:=maxlen;
  2031. i:=f.Read(FPosnblock^.data[FPosnblock^.used],left);
  2032. dec(maxlen,i);
  2033. inc(FPosnblock^.used,i);
  2034. if FPosnblock^.used=blocksize then
  2035. begin
  2036. if assigned(FPosnblock^.Next) then
  2037. FPosnblock:=FPosnblock^.Next
  2038. else
  2039. begin
  2040. grow;
  2041. FPosnblock:=FLastblock;
  2042. end;
  2043. end;
  2044. until (i<left) or (maxlen=0);
  2045. end;
  2046. procedure tdynamicarray.writestream(f:TCStream);
  2047. var
  2048. hp : pdynamicblock;
  2049. begin
  2050. hp:=FFirstblock;
  2051. while assigned(hp) do
  2052. begin
  2053. f.Write(hp^.data,hp^.used);
  2054. hp:=hp^.Next;
  2055. end;
  2056. end;
  2057. end.
  2058. {
  2059. $Log: cclasses.pas,v $
  2060. Revision 1.45 2005/05/12 21:40:42 hajny
  2061. * fix for SIGSEGV due to access to uninitialized pointers in TList
  2062. Revision 1.44 2005/03/25 23:03:04 jonas
  2063. - removed unused variables
  2064. Revision 1.43 2005/03/04 16:49:22 peter
  2065. * getheapstatus fixes
  2066. Revision 1.42 2005/02/28 15:38:38 marco
  2067. * getFPCheapstatus (no, FPC HEAP, not FP CHEAP!)
  2068. Revision 1.41 2005/02/14 17:13:06 peter
  2069. * truncate log
  2070. }