cobjects.pas 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This module provides some basic objects
  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. {$ifdef tp}
  19. {$E+,N+,D+,F+}
  20. {$endif}
  21. {$I-}
  22. {$R-}{ necessary for crc calculation and dynamicblock acessing }
  23. {$ifdef fpc}
  24. {$define USEREALLOCMEM}
  25. {$endif fpc}
  26. {$ifdef delphi}
  27. {$define USEREALLOCMEM}
  28. {$endif delphi}
  29. unit cobjects;
  30. { define OLDSPEEDVALUE}
  31. interface
  32. uses
  33. {$ifdef DELPHI4}
  34. dmisc,
  35. sysutils
  36. {$else DELPHI4}
  37. strings
  38. {$ifndef linux}
  39. ,dos
  40. {$else}
  41. ,linux
  42. {$endif}
  43. {$endif DELPHI4}
  44. ;
  45. const
  46. { the real size will be [-hasharray..hasharray] ! }
  47. {$ifdef TP}
  48. hasharraysize = 127;
  49. {$else}
  50. hasharraysize = 2047;
  51. {$endif}
  52. type
  53. pstring = ^string;
  54. {$ifdef TP}
  55. { redeclare dword only in case of emergency, some small things
  56. of the compiler won't work then correctly (FK)
  57. }
  58. dword = longint;
  59. {$endif TP}
  60. pfileposinfo = ^tfileposinfo;
  61. tfileposinfo = record
  62. line : longint;
  63. column : word;
  64. fileindex : word;
  65. end;
  66. pmemdebug = ^tmemdebug;
  67. tmemdebug = object
  68. constructor init(const s:string);
  69. destructor done;
  70. procedure show;
  71. private
  72. startmem : longint;
  73. infostr : string[40];
  74. end;
  75. plinkedlist_item = ^tlinkedlist_item;
  76. tlinkedlist_item = object
  77. next,previous : plinkedlist_item;
  78. { does nothing }
  79. constructor init;
  80. destructor done;virtual;
  81. function getcopy:plinkedlist_item;virtual;
  82. end;
  83. pstring_item = ^tstring_item;
  84. tstring_item = object(tlinkedlist_item)
  85. str : pstring;
  86. constructor init(const s : string);
  87. destructor done;virtual;
  88. end;
  89. { this implements a double linked list }
  90. plinkedlist = ^tlinkedlist;
  91. tlinkedlist = object
  92. first,last : plinkedlist_item;
  93. constructor init;
  94. destructor done;
  95. { disposes the items of the list }
  96. procedure clear;
  97. { concats a new item at the end }
  98. procedure concat(p : plinkedlist_item);
  99. { inserts a new item at the begin }
  100. procedure insert(p : plinkedlist_item);
  101. { inserts another list at the begin and make this list empty }
  102. procedure insertlist(p : plinkedlist);
  103. { concats another list at the end and make this list empty }
  104. procedure concatlist(p : plinkedlist);
  105. procedure concatlistcopy(p : plinkedlist);
  106. { removes p from the list (p isn't disposed) }
  107. { it's not tested if p is in the list ! }
  108. procedure remove(p : plinkedlist_item);
  109. { is the linkedlist empty ? }
  110. function empty:boolean;
  111. { items in the list }
  112. function count:longint;
  113. end;
  114. { some help data types }
  115. pstringqueueitem = ^tstringqueueitem;
  116. tstringqueueitem = object
  117. data : pstring;
  118. next : pstringqueueitem;
  119. end;
  120. { String Queue}
  121. PStringQueue=^TStringQueue;
  122. TStringQueue=object
  123. first,last : PStringqueueItem;
  124. constructor Init;
  125. destructor Done;
  126. function Empty:boolean;
  127. function Get:string;
  128. function Find(const s:string):PStringqueueItem;
  129. function Delete(const s:string):boolean;
  130. procedure Insert(const s:string);
  131. procedure Concat(const s:string);
  132. procedure Clear;
  133. end;
  134. { containeritem }
  135. pcontaineritem = ^tcontaineritem;
  136. tcontaineritem = object
  137. next : pcontaineritem;
  138. constructor init;
  139. destructor done;virtual;
  140. end;
  141. { container }
  142. pcontainer = ^tcontainer;
  143. tcontainer = object
  144. root,
  145. last : pcontaineritem;
  146. constructor init;
  147. destructor done;
  148. { true when the container is empty }
  149. function empty:boolean;
  150. { amount of strings in the container }
  151. function count:longint;
  152. { inserts a string }
  153. procedure insert(item:pcontaineritem);
  154. { gets a string }
  155. function get:pcontaineritem;
  156. { deletes all items }
  157. procedure clear;
  158. end;
  159. { containeritem }
  160. pstringcontaineritem = ^tstringcontaineritem;
  161. tstringcontaineritem = object(tcontaineritem)
  162. data : pstring;
  163. file_info : tfileposinfo;
  164. constructor init(const s:string);
  165. constructor Init_TokenInfo(const s:string;const pos:tfileposinfo);
  166. destructor done;virtual;
  167. end;
  168. { string container }
  169. pstringcontainer = ^tstringcontainer;
  170. tstringcontainer = object(tcontainer)
  171. doubles : boolean; { if this is set to true, doubles are allowed }
  172. constructor init;
  173. constructor init_no_double;
  174. procedure insert(const s : string);
  175. procedure insert_with_tokeninfo(const s : string;const file_info : tfileposinfo);
  176. { gets a string }
  177. function get : string;
  178. function get_with_tokeninfo(var file_info : tfileposinfo) : string;
  179. { true if string is in the container }
  180. function find(const s:string):boolean;
  181. end;
  182. { namedindexobject for use with dictionary and indexarray }
  183. Pnamedindexobject=^Tnamedindexobject;
  184. Tnamedindexobject=object
  185. { indexarray }
  186. indexnr : longint;
  187. indexnext : Pnamedindexobject;
  188. { dictionary }
  189. _name : Pstring;
  190. left,right : Pnamedindexobject;
  191. speedvalue : longint;
  192. { singlelist }
  193. listnext : Pnamedindexobject;
  194. constructor init;
  195. constructor initname(const n:string);
  196. destructor done;virtual;
  197. procedure setname(const n:string);virtual;
  198. function name:string;virtual;
  199. end;
  200. Pdictionaryhasharray=^Tdictionaryhasharray;
  201. Tdictionaryhasharray=array[-hasharraysize..hasharraysize] of Pnamedindexobject;
  202. Tnamedindexcallback = procedure(p:Pnamedindexobject);
  203. Pdictionary=^Tdictionary;
  204. Tdictionary=object
  205. noclear : boolean;
  206. replace_existing : boolean;
  207. constructor init;
  208. destructor done;virtual;
  209. procedure usehash;
  210. procedure clear;
  211. function delete(const s:string):Pnamedindexobject;
  212. function empty:boolean;
  213. procedure foreach(proc2call:Tnamedindexcallback);
  214. function insert(obj:Pnamedindexobject):Pnamedindexobject;
  215. function rename(const olds,news : string):Pnamedindexobject;
  216. function search(const s:string):Pnamedindexobject;
  217. function speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  218. private
  219. root : Pnamedindexobject;
  220. hasharray : Pdictionaryhasharray;
  221. procedure cleartree(obj:Pnamedindexobject);
  222. function insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  223. procedure inserttree(currtree,currroot:Pnamedindexobject);
  224. end;
  225. psinglelist=^tsinglelist;
  226. tsinglelist=object
  227. noclear : boolean;
  228. first,
  229. last : Pnamedindexobject;
  230. constructor init;
  231. destructor done;
  232. procedure clear;
  233. procedure insert(p:Pnamedindexobject);
  234. end;
  235. const
  236. dynamicblockbasesize = 12;
  237. type
  238. pdynamicblock = ^tdynamicblock;
  239. tdynamicblock = record
  240. pos,
  241. used : longint;
  242. next : pdynamicblock;
  243. data : array[0..1] of byte;
  244. end;
  245. pdynamicarray = ^tdynamicarray;
  246. tdynamicarray = object
  247. blocksize : longint;
  248. firstblock,
  249. lastblock : pdynamicblock;
  250. constructor init(Ablocksize:longint);
  251. destructor done;
  252. function size:longint;
  253. procedure align(i:longint);
  254. procedure seek(i:longint);
  255. procedure write(var d;len:longint);
  256. function read(var d;len:longint):longint;
  257. procedure blockwrite(var f:file);
  258. private
  259. posn : longint;
  260. posnblock : pdynamicblock;
  261. procedure grow;
  262. end;
  263. tindexobjectarray=array[1..16000] of Pnamedindexobject;
  264. Pnamedindexobjectarray=^tindexobjectarray;
  265. pindexarray=^tindexarray;
  266. tindexarray=object
  267. noclear : boolean;
  268. first : Pnamedindexobject;
  269. count : longint;
  270. constructor init(Agrowsize:longint);
  271. destructor done;
  272. procedure clear;
  273. procedure foreach(proc2call : Tnamedindexcallback);
  274. procedure deleteindex(p:Pnamedindexobject);
  275. procedure delete(p:Pnamedindexobject);
  276. procedure insert(p:Pnamedindexobject);
  277. function search(nr:longint):Pnamedindexobject;
  278. private
  279. growsize,
  280. size : longint;
  281. data : Pnamedindexobjectarray;
  282. procedure grow(gsize:longint);
  283. end;
  284. {$ifdef BUFFEREDFILE}
  285. { this is implemented to allow buffered binary I/O }
  286. pbufferedfile = ^tbufferedfile;
  287. tbufferedfile = object
  288. f : file;
  289. buf : pchar;
  290. bufsize,buflast,bufpos : longint;
  291. { 0 closed, 1 input, 2 output }
  292. iomode : byte;
  293. { true, if the compile should change the endian of the output }
  294. change_endian : boolean;
  295. { calcules a crc for the file, }
  296. { but it's assumed, that there no seek while do_crc is true }
  297. do_crc : boolean;
  298. crc : longint;
  299. { temporary closing feature }
  300. tempclosed : boolean;
  301. tempmode : byte;
  302. temppos : longint;
  303. { inits a buffer with the size bufsize which is assigned to }
  304. { the file filename }
  305. constructor init(const filename : string;_bufsize : longint);
  306. { closes the file, if needed, and releases the memory }
  307. destructor done;virtual;
  308. { opens the file for input, other accesses are rejected }
  309. function reset:boolean;
  310. { opens the file for output, other accesses are rejected }
  311. procedure rewrite;
  312. { reads or writes the buffer from or to disk }
  313. procedure flush;
  314. { writes a string to the file }
  315. { the string is written without a length byte }
  316. procedure write_string(const s : string);
  317. { writes a zero terminated string }
  318. procedure write_pchar(p : pchar);
  319. { write specific data types, takes care of }
  320. { byte order }
  321. procedure write_byte(b : byte);
  322. procedure write_word(w : word);
  323. procedure write_long(l : longint);
  324. procedure write_double(d : double);
  325. { writes any data }
  326. procedure write_data(var data;count : longint);
  327. { reads any data }
  328. procedure read_data(var data;bytes : longint;var count : longint);
  329. { closes the file and releases the buffer }
  330. procedure close;
  331. { temporary closing }
  332. procedure tempclose;
  333. procedure tempreopen;
  334. { goto the given position }
  335. procedure seek(l : longint);
  336. { installes an user defined buffer }
  337. { and releases the old one, but be }
  338. { careful, if the old buffer contains }
  339. { data, this data is lost }
  340. procedure setbuf(p : pchar;s : longint);
  341. { reads the file time stamp of the file, }
  342. { the file must be opened }
  343. function getftime : longint;
  344. { returns filesize }
  345. function getsize : longint;
  346. { returns the path }
  347. function getpath : string;
  348. { resets the crc }
  349. procedure clear_crc;
  350. { returns the crc }
  351. function getcrc : longint;
  352. end;
  353. {$endif BUFFEREDFILE}
  354. {$ifdef fixLeaksOnError}
  355. PStackItem = ^TStackItem;
  356. TStackItem = record
  357. next: PStackItem;
  358. data: pointer;
  359. end;
  360. PStack = ^TStack;
  361. TStack = object
  362. constructor init;
  363. destructor done;
  364. procedure push(p: pointer);
  365. function pop: pointer;
  366. function top: pointer;
  367. function isEmpty: boolean;
  368. private
  369. head: PStackItem;
  370. end;
  371. {$endif fixLeaksOnError}
  372. function getspeedvalue(const s : string) : longint;
  373. { releases the string p and assignes nil to p }
  374. { if p=nil then freemem isn't called }
  375. procedure stringdispose(var p : pstring);
  376. { idem for ansistrings }
  377. procedure ansistringdispose(var p : pchar;length : longint);
  378. { allocates mem for a copy of s, copies s to this mem and returns }
  379. { a pointer to this mem }
  380. function stringdup(const s : string) : pstring;
  381. { allocates memory for s and copies s as zero terminated string
  382. to that mem and returns a pointer to that mem }
  383. function strpnew(const s : string) : pchar;
  384. procedure strdispose(var p : pchar);
  385. { makes a char lowercase, with spanish, french and german char set }
  386. function lowercase(c : char) : char;
  387. { makes zero terminated string to a pascal string }
  388. { the data in p is modified and p is returned }
  389. function pchar2pstring(p : pchar) : pstring;
  390. { ambivalent to pchar2pstring }
  391. function pstring2pchar(p : pstring) : pchar;
  392. implementation
  393. uses
  394. comphook;
  395. {*****************************************************************************
  396. Memory debug
  397. *****************************************************************************}
  398. constructor tmemdebug.init(const s:string);
  399. begin
  400. infostr:=s;
  401. {$ifdef Delphi}
  402. startmem:=0;
  403. {$else}
  404. startmem:=memavail;
  405. {$endif Delphi}
  406. end;
  407. procedure tmemdebug.show;
  408. var
  409. l : longint;
  410. begin
  411. {$ifndef Delphi}
  412. write('memory [',infostr,'] ');
  413. l:=memavail;
  414. if l>startmem then
  415. writeln(l-startmem,' released')
  416. else
  417. writeln(startmem-l,' allocated');
  418. {$endif Delphi}
  419. end;
  420. destructor tmemdebug.done;
  421. begin
  422. show;
  423. end;
  424. {*****************************************************************************
  425. Stack
  426. *****************************************************************************}
  427. {$ifdef fixLeaksOnError}
  428. constructor TStack.init;
  429. begin
  430. head := nil;
  431. end;
  432. procedure TStack.push(p: pointer);
  433. var s: PStackItem;
  434. begin
  435. new(s);
  436. s^.data := p;
  437. s^.next := head;
  438. head := s;
  439. end;
  440. function TStack.pop: pointer;
  441. var s: PStackItem;
  442. begin
  443. pop := top;
  444. if assigned(head) then
  445. begin
  446. s := head^.next;
  447. dispose(head);
  448. head := s;
  449. end
  450. end;
  451. function TStack.top: pointer;
  452. begin
  453. if not isEmpty then
  454. top := head^.data
  455. else top := NIL;
  456. end;
  457. function TStack.isEmpty: boolean;
  458. begin
  459. isEmpty := head = nil;
  460. end;
  461. destructor TStack.done;
  462. var temp: PStackItem;
  463. begin
  464. while head <> nil do
  465. begin
  466. temp := head^.next;
  467. dispose(head);
  468. head := temp;
  469. end;
  470. end;
  471. {$endif fixLeaksOnError}
  472. {$ifndef OLDSPEEDVALUE}
  473. {*****************************************************************************
  474. Crc 32
  475. *****************************************************************************}
  476. var
  477. Crc32Tbl : array[0..255] of longint;
  478. procedure MakeCRC32Tbl;
  479. var
  480. crc : longint;
  481. i,n : byte;
  482. begin
  483. for i:=0 to 255 do
  484. begin
  485. crc:=i;
  486. for n:=1 to 8 do
  487. if odd(crc) then
  488. crc:=(crc shr 1) xor longint($edb88320)
  489. else
  490. crc:=crc shr 1;
  491. Crc32Tbl[i]:=crc;
  492. end;
  493. end;
  494. {$ifopt R+}
  495. {$define Range_check_on}
  496. {$endif opt R+}
  497. {$R- needed here }
  498. {CRC 32}
  499. Function GetSpeedValue(Const s:String):longint;
  500. var
  501. i,InitCrc : longint;
  502. begin
  503. if Crc32Tbl[1]=0 then
  504. MakeCrc32Tbl;
  505. InitCrc:=$ffffffff;
  506. for i:=1 to Length(s) do
  507. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  508. GetSpeedValue:=InitCrc;
  509. end;
  510. {$ifdef Range_check_on}
  511. {$R+}
  512. {$undef Range_check_on}
  513. {$endif Range_check_on}
  514. {$else}
  515. {$ifndef TP}
  516. function getspeedvalue(const s : string) : longint;
  517. var
  518. p1,p2:^byte;
  519. i : longint;
  520. begin
  521. p1:=@s;
  522. longint(p2):=longint(p1)+p1^+1;
  523. inc(longint(p1));
  524. i:=0;
  525. while p1<>p2 do
  526. begin
  527. i:=i + ord(p1^);
  528. inc(longint(p1));
  529. end;
  530. getspeedvalue:=i;
  531. end;
  532. {$else}
  533. function getspeedvalue(const s : string) : longint;
  534. type
  535. ptrrec=record
  536. ofs,seg:word;
  537. end;
  538. var
  539. l,w : longint;
  540. p1,p2 : ^byte;
  541. begin
  542. p1:=@s;
  543. ptrrec(p2).seg:=ptrrec(p1).seg;
  544. ptrrec(p2).ofs:=ptrrec(p1).ofs+p1^+1;
  545. inc(p1);
  546. l:=0;
  547. while p1<>p2 do
  548. begin
  549. l:=l + ord(p1^);
  550. inc(p1);
  551. end;
  552. getspeedvalue:=l;
  553. end;
  554. {$endif}
  555. {$endif OLDSPEEDVALUE}
  556. function pchar2pstring(p : pchar) : pstring;
  557. var
  558. w,i : longint;
  559. begin
  560. w:=strlen(p);
  561. for i:=w-1 downto 0 do
  562. p[i+1]:=p[i];
  563. p[0]:=chr(w);
  564. pchar2pstring:=pstring(p);
  565. end;
  566. function pstring2pchar(p : pstring) : pchar;
  567. var
  568. w,i : longint;
  569. begin
  570. w:=length(p^);
  571. for i:=1 to w do
  572. p^[i-1]:=p^[i];
  573. p^[w]:=#0;
  574. pstring2pchar:=pchar(p);
  575. end;
  576. function lowercase(c : char) : char;
  577. begin
  578. case c of
  579. #65..#90 : c := chr(ord (c) + 32);
  580. #154 : c:=#129; { german }
  581. #142 : c:=#132; { german }
  582. #153 : c:=#148; { german }
  583. #144 : c:=#130; { french }
  584. #128 : c:=#135; { french }
  585. #143 : c:=#134; { swedish/norge (?) }
  586. #165 : c:=#164; { spanish }
  587. #228 : c:=#229; { greek }
  588. #226 : c:=#231; { greek }
  589. #232 : c:=#227; { greek }
  590. end;
  591. lowercase := c;
  592. end;
  593. function strpnew(const s : string) : pchar;
  594. var
  595. p : pchar;
  596. begin
  597. getmem(p,length(s)+1);
  598. strpcopy(p,s);
  599. strpnew:=p;
  600. end;
  601. procedure strdispose(var p : pchar);
  602. begin
  603. if assigned(p) then
  604. begin
  605. freemem(p,strlen(p)+1);
  606. p:=nil;
  607. end;
  608. end;
  609. procedure stringdispose(var p : pstring);
  610. begin
  611. if assigned(p) then
  612. freemem(p,length(p^)+1);
  613. p:=nil;
  614. end;
  615. procedure ansistringdispose(var p : pchar;length : longint);
  616. begin
  617. if assigned(p) then
  618. freemem(p,length+1);
  619. p:=nil;
  620. end;
  621. function stringdup(const s : string) : pstring;
  622. var
  623. p : pstring;
  624. begin
  625. getmem(p,length(s)+1);
  626. p^:=s;
  627. stringdup:=p;
  628. end;
  629. {****************************************************************************
  630. TStringQueue
  631. ****************************************************************************}
  632. constructor TStringQueue.Init;
  633. begin
  634. first:=nil;
  635. last:=nil;
  636. end;
  637. function TStringQueue.Empty:boolean;
  638. begin
  639. Empty:=(first=nil);
  640. end;
  641. function TStringQueue.Get:string;
  642. var
  643. newnode : pstringqueueitem;
  644. begin
  645. if first=nil then
  646. begin
  647. Get:='';
  648. exit;
  649. end;
  650. Get:=first^.data^;
  651. stringdispose(first^.data);
  652. newnode:=first;
  653. first:=first^.next;
  654. dispose(newnode);
  655. end;
  656. function TStringQueue.Find(const s:string):PStringqueueItem;
  657. var
  658. p : PStringqueueItem;
  659. begin
  660. p:=first;
  661. while assigned(p) do
  662. begin
  663. if p^.data^=s then
  664. break;
  665. p:=p^.next;
  666. end;
  667. Find:=p;
  668. end;
  669. function TStringQueue.Delete(const s:string):boolean;
  670. var
  671. prev,p : PStringqueueItem;
  672. begin
  673. Delete:=false;
  674. prev:=nil;
  675. p:=first;
  676. while assigned(p) do
  677. begin
  678. if p^.data^=s then
  679. begin
  680. if p=last then
  681. last:=prev;
  682. if assigned(prev) then
  683. prev^.next:=p^.next
  684. else
  685. first:=p^.next;
  686. dispose(p);
  687. Delete:=true;
  688. exit;
  689. end;
  690. prev:=p;
  691. p:=p^.next;
  692. end;
  693. end;
  694. procedure TStringQueue.Insert(const s:string);
  695. var
  696. newnode : pstringqueueitem;
  697. begin
  698. new(newnode);
  699. newnode^.next:=first;
  700. newnode^.data:=stringdup(s);
  701. first:=newnode;
  702. if last=nil then
  703. last:=newnode;
  704. end;
  705. procedure TStringQueue.Concat(const s:string);
  706. var
  707. newnode : pstringqueueitem;
  708. begin
  709. new(newnode);
  710. newnode^.next:=nil;
  711. newnode^.data:=stringdup(s);
  712. if first=nil then
  713. first:=newnode
  714. else
  715. last^.next:=newnode;
  716. last:=newnode;
  717. end;
  718. procedure TStringQueue.Clear;
  719. var
  720. newnode : pstringqueueitem;
  721. begin
  722. while (first<>nil) do
  723. begin
  724. newnode:=first;
  725. stringdispose(first^.data);
  726. first:=first^.next;
  727. dispose(newnode);
  728. end;
  729. last:=nil;
  730. end;
  731. destructor TStringQueue.Done;
  732. begin
  733. Clear;
  734. end;
  735. {****************************************************************************
  736. TContainerItem
  737. ****************************************************************************}
  738. constructor TContainerItem.Init;
  739. begin
  740. end;
  741. destructor TContainerItem.Done;
  742. begin
  743. end;
  744. {****************************************************************************
  745. TStringContainerItem
  746. ****************************************************************************}
  747. constructor TStringContainerItem.Init(const s:string);
  748. begin
  749. inherited Init;
  750. data:=stringdup(s);
  751. file_info.fileindex:=0;
  752. file_info.line:=0;
  753. file_info.column:=0;
  754. end;
  755. constructor TStringContainerItem.Init_TokenInfo(const s:string;const pos:tfileposinfo);
  756. begin
  757. inherited Init;
  758. data:=stringdup(s);
  759. file_info:=pos;
  760. end;
  761. destructor TStringContainerItem.Done;
  762. begin
  763. stringdispose(data);
  764. end;
  765. {****************************************************************************
  766. TCONTAINER
  767. ****************************************************************************}
  768. constructor tcontainer.init;
  769. begin
  770. root:=nil;
  771. last:=nil;
  772. end;
  773. destructor tcontainer.done;
  774. begin
  775. clear;
  776. end;
  777. function tcontainer.empty:boolean;
  778. begin
  779. empty:=(root=nil);
  780. end;
  781. function tcontainer.count:longint;
  782. var
  783. i : longint;
  784. p : pcontaineritem;
  785. begin
  786. i:=0;
  787. p:=root;
  788. while assigned(p) do
  789. begin
  790. p:=p^.next;
  791. inc(i);
  792. end;
  793. count:=i;
  794. end;
  795. procedure tcontainer.insert(item:pcontaineritem);
  796. begin
  797. item^.next:=nil;
  798. if root=nil then
  799. root:=item
  800. else
  801. last^.next:=item;
  802. last:=item;
  803. end;
  804. procedure tcontainer.clear;
  805. var
  806. newnode : pcontaineritem;
  807. begin
  808. newnode:=root;
  809. while assigned(newnode) do
  810. begin
  811. root:=newnode^.next;
  812. dispose(newnode,done);
  813. newnode:=root;
  814. end;
  815. last:=nil;
  816. root:=nil;
  817. end;
  818. function tcontainer.get:pcontaineritem;
  819. begin
  820. if root=nil then
  821. get:=nil
  822. else
  823. begin
  824. get:=root;
  825. root:=root^.next;
  826. end;
  827. end;
  828. {****************************************************************************
  829. TSTRINGCONTAINER
  830. ****************************************************************************}
  831. constructor tstringcontainer.init;
  832. begin
  833. inherited init;
  834. doubles:=true;
  835. end;
  836. constructor tstringcontainer.init_no_double;
  837. begin
  838. inherited init;
  839. doubles:=false;
  840. end;
  841. procedure tstringcontainer.insert(const s : string);
  842. var
  843. newnode : pstringcontaineritem;
  844. begin
  845. if (s='') or
  846. ((not doubles) and find(s)) then
  847. exit;
  848. new(newnode,init(s));
  849. inherited insert(newnode);
  850. end;
  851. procedure tstringcontainer.insert_with_tokeninfo(const s : string; const file_info : tfileposinfo);
  852. var
  853. newnode : pstringcontaineritem;
  854. begin
  855. if (not doubles) and find(s) then
  856. exit;
  857. new(newnode,init_tokeninfo(s,file_info));
  858. inherited insert(newnode);
  859. end;
  860. function tstringcontainer.get : string;
  861. var
  862. p : pstringcontaineritem;
  863. begin
  864. p:=pstringcontaineritem(inherited get);
  865. if p=nil then
  866. get:=''
  867. else
  868. begin
  869. get:=p^.data^;
  870. dispose(p,done);
  871. end;
  872. end;
  873. function tstringcontainer.get_with_tokeninfo(var file_info : tfileposinfo) : string;
  874. var
  875. p : pstringcontaineritem;
  876. begin
  877. p:=pstringcontaineritem(inherited get);
  878. if p=nil then
  879. begin
  880. get_with_tokeninfo:='';
  881. file_info.fileindex:=0;
  882. file_info.line:=0;
  883. file_info.column:=0;
  884. end
  885. else
  886. begin
  887. get_with_tokeninfo:=p^.data^;
  888. file_info:=p^.file_info;
  889. dispose(p,done);
  890. end;
  891. end;
  892. function tstringcontainer.find(const s:string):boolean;
  893. var
  894. newnode : pstringcontaineritem;
  895. begin
  896. find:=false;
  897. newnode:=pstringcontaineritem(root);
  898. while assigned(newnode) do
  899. begin
  900. if newnode^.data^=s then
  901. begin
  902. find:=true;
  903. exit;
  904. end;
  905. newnode:=pstringcontaineritem(newnode^.next);
  906. end;
  907. end;
  908. {****************************************************************************
  909. TLINKEDLIST_ITEM
  910. ****************************************************************************}
  911. constructor tlinkedlist_item.init;
  912. begin
  913. previous:=nil;
  914. next:=nil;
  915. end;
  916. destructor tlinkedlist_item.done;
  917. begin
  918. end;
  919. function tlinkedlist_item.getcopy:plinkedlist_item;
  920. var
  921. l : longint;
  922. p : plinkedlist_item;
  923. begin
  924. l:=sizeof(self);
  925. getmem(p,l);
  926. move(self,p^,l);
  927. getcopy:=p;
  928. end;
  929. {****************************************************************************
  930. TSTRING_ITEM
  931. ****************************************************************************}
  932. constructor tstring_item.init(const s : string);
  933. begin
  934. str:=stringdup(s);
  935. end;
  936. destructor tstring_item.done;
  937. begin
  938. stringdispose(str);
  939. inherited done;
  940. end;
  941. {****************************************************************************
  942. TLINKEDLIST
  943. ****************************************************************************}
  944. constructor tlinkedlist.init;
  945. begin
  946. first:=nil;
  947. last:=nil;
  948. end;
  949. destructor tlinkedlist.done;
  950. begin
  951. clear;
  952. end;
  953. procedure tlinkedlist.clear;
  954. var
  955. newnode : plinkedlist_item;
  956. begin
  957. newnode:=first;
  958. while assigned(newnode) do
  959. begin
  960. first:=newnode^.next;
  961. dispose(newnode,done);
  962. newnode:=first;
  963. end;
  964. end;
  965. procedure tlinkedlist.insertlist(p : plinkedlist);
  966. begin
  967. { empty list ? }
  968. if not(assigned(p^.first)) then
  969. exit;
  970. p^.last^.next:=first;
  971. { we have a double linked list }
  972. if assigned(first) then
  973. first^.previous:=p^.last;
  974. first:=p^.first;
  975. if not(assigned(last)) then
  976. last:=p^.last;
  977. { p becomes empty }
  978. p^.first:=nil;
  979. p^.last:=nil;
  980. end;
  981. procedure tlinkedlist.concat(p : plinkedlist_item);
  982. begin
  983. if not(assigned(first)) then
  984. begin
  985. first:=p;
  986. p^.previous:=nil;
  987. p^.next:=nil;
  988. end
  989. else
  990. begin
  991. last^.next:=p;
  992. p^.previous:=last;
  993. p^.next:=nil;
  994. end;
  995. last:=p;
  996. end;
  997. procedure tlinkedlist.insert(p : plinkedlist_item);
  998. begin
  999. if not(assigned(first)) then
  1000. begin
  1001. last:=p;
  1002. p^.previous:=nil;
  1003. p^.next:=nil;
  1004. end
  1005. else
  1006. begin
  1007. first^.previous:=p;
  1008. p^.previous:=nil;
  1009. p^.next:=first;
  1010. end;
  1011. first:=p;
  1012. end;
  1013. procedure tlinkedlist.remove(p : plinkedlist_item);
  1014. begin
  1015. if not(assigned(p)) then
  1016. exit;
  1017. if (first=p) and (last=p) then
  1018. begin
  1019. first:=nil;
  1020. last:=nil;
  1021. end
  1022. else if first=p then
  1023. begin
  1024. first:=p^.next;
  1025. if assigned(first) then
  1026. first^.previous:=nil;
  1027. end
  1028. else if last=p then
  1029. begin
  1030. last:=last^.previous;
  1031. if assigned(last) then
  1032. last^.next:=nil;
  1033. end
  1034. else
  1035. begin
  1036. p^.previous^.next:=p^.next;
  1037. p^.next^.previous:=p^.previous;
  1038. end;
  1039. p^.next:=nil;
  1040. p^.previous:=nil;
  1041. end;
  1042. procedure tlinkedlist.concatlist(p : plinkedlist);
  1043. begin
  1044. if not(assigned(p^.first)) then
  1045. exit;
  1046. if not(assigned(first)) then
  1047. first:=p^.first
  1048. else
  1049. begin
  1050. last^.next:=p^.first;
  1051. p^.first^.previous:=last;
  1052. end;
  1053. last:=p^.last;
  1054. { make p empty }
  1055. p^.last:=nil;
  1056. p^.first:=nil;
  1057. end;
  1058. procedure tlinkedlist.concatlistcopy(p : plinkedlist);
  1059. var
  1060. newnode,newnode2 : plinkedlist_item;
  1061. begin
  1062. newnode:=p^.first;
  1063. while assigned(newnode) do
  1064. begin
  1065. newnode2:=newnode^.getcopy;
  1066. if assigned(newnode2) then
  1067. begin
  1068. if not(assigned(first)) then
  1069. begin
  1070. first:=newnode2;
  1071. newnode2^.previous:=nil;
  1072. newnode2^.next:=nil;
  1073. end
  1074. else
  1075. begin
  1076. last^.next:=newnode2;
  1077. newnode2^.previous:=last;
  1078. newnode2^.next:=nil;
  1079. end;
  1080. last:=newnode2;
  1081. end;
  1082. newnode:=newnode^.next;
  1083. end;
  1084. end;
  1085. function tlinkedlist.empty:boolean;
  1086. begin
  1087. empty:=(first=nil);
  1088. end;
  1089. function tlinkedlist.count:longint;
  1090. var
  1091. i : longint;
  1092. hp : plinkedlist_item;
  1093. begin
  1094. hp:=first;
  1095. i:=0;
  1096. while assigned(hp) do
  1097. begin
  1098. inc(i);
  1099. hp:=hp^.next;
  1100. end;
  1101. count:=i;
  1102. end;
  1103. {****************************************************************************
  1104. Tnamedindexobject
  1105. ****************************************************************************}
  1106. constructor Tnamedindexobject.init;
  1107. begin
  1108. { index }
  1109. indexnr:=-1;
  1110. indexnext:=nil;
  1111. { dictionary }
  1112. left:=nil;
  1113. right:=nil;
  1114. _name:=nil;
  1115. speedvalue:=-1;
  1116. { list }
  1117. listnext:=nil;
  1118. end;
  1119. constructor Tnamedindexobject.initname(const n:string);
  1120. begin
  1121. { index }
  1122. indexnr:=-1;
  1123. indexnext:=nil;
  1124. { dictionary }
  1125. left:=nil;
  1126. right:=nil;
  1127. speedvalue:=-1;
  1128. _name:=stringdup(n);
  1129. { list }
  1130. listnext:=nil;
  1131. end;
  1132. destructor Tnamedindexobject.done;
  1133. begin
  1134. stringdispose(_name);
  1135. end;
  1136. procedure Tnamedindexobject.setname(const n:string);
  1137. begin
  1138. if speedvalue=-1 then
  1139. begin
  1140. if assigned(_name) then
  1141. stringdispose(_name);
  1142. _name:=stringdup(n);
  1143. end;
  1144. end;
  1145. function Tnamedindexobject.name:string;
  1146. begin
  1147. if assigned(_name) then
  1148. name:=_name^
  1149. else
  1150. name:='';
  1151. end;
  1152. {****************************************************************************
  1153. TDICTIONARY
  1154. ****************************************************************************}
  1155. constructor Tdictionary.init;
  1156. begin
  1157. root:=nil;
  1158. hasharray:=nil;
  1159. noclear:=false;
  1160. replace_existing:=false;
  1161. end;
  1162. procedure Tdictionary.usehash;
  1163. begin
  1164. if not(assigned(root)) and
  1165. not(assigned(hasharray)) then
  1166. begin
  1167. new(hasharray);
  1168. fillchar(hasharray^,sizeof(hasharray^),0);
  1169. end;
  1170. end;
  1171. destructor Tdictionary.done;
  1172. begin
  1173. if not noclear then
  1174. clear;
  1175. if assigned(hasharray) then
  1176. dispose(hasharray);
  1177. end;
  1178. procedure Tdictionary.cleartree(obj:Pnamedindexobject);
  1179. begin
  1180. if assigned(obj^.left) then
  1181. cleartree(obj^.left);
  1182. if assigned(obj^.right) then
  1183. cleartree(obj^.right);
  1184. dispose(obj,done);
  1185. obj:=nil;
  1186. end;
  1187. procedure Tdictionary.clear;
  1188. var
  1189. w : longint;
  1190. begin
  1191. if assigned(root) then
  1192. cleartree(root);
  1193. if assigned(hasharray) then
  1194. for w:=-hasharraysize to hasharraysize do
  1195. if assigned(hasharray^[w]) then
  1196. cleartree(hasharray^[w]);
  1197. end;
  1198. function Tdictionary.delete(const s:string):Pnamedindexobject;
  1199. var p,speedvalue:longint;
  1200. n:Pnamedindexobject;
  1201. procedure insert_right_bottom(var root,Atree:Pnamedindexobject);
  1202. begin
  1203. while root^.right<>nil do
  1204. root:=root^.right;
  1205. root^.right:=Atree;
  1206. end;
  1207. function delete_from_tree(root:Pnamedindexobject):Pnamedindexobject;
  1208. type leftright=(left,right);
  1209. var lr:leftright;
  1210. oldroot:Pnamedindexobject;
  1211. begin
  1212. oldroot:=nil;
  1213. while (root<>nil) and (root^.speedvalue<>speedvalue) do
  1214. begin
  1215. oldroot:=root;
  1216. if speedvalue<root^.speedvalue then
  1217. begin
  1218. root:=root^.right;
  1219. lr:=right;
  1220. end
  1221. else
  1222. begin
  1223. root:=root^.left;
  1224. lr:=left;
  1225. end;
  1226. end;
  1227. while (root<>nil) and (root^._name^<>s) do
  1228. begin
  1229. oldroot:=root;
  1230. if s<root^._name^ then
  1231. begin
  1232. root:=root^.right;
  1233. lr:=right;
  1234. end
  1235. else
  1236. begin
  1237. root:=root^.left;
  1238. lr:=left;
  1239. end;
  1240. end;
  1241. if (oldroot=nil) or (root=nil) then
  1242. do_internalerror(218); {Internalerror is not available...}
  1243. if root^.left<>nil then
  1244. begin
  1245. {Now the node pointing to root must point to the left
  1246. subtree of root. The right subtree of root must be
  1247. connected to the right bottom of the left subtree.}
  1248. if lr=left then
  1249. oldroot^.left:=root^.left
  1250. else
  1251. oldroot^.right:=root^.left;
  1252. if root^.right<>nil then
  1253. insert_right_bottom(root^.left,root^.right);
  1254. end
  1255. else
  1256. {There is no left subtree. So we can just replace the node to
  1257. delete with the right subtree.}
  1258. if lr=left then
  1259. oldroot^.left:=root^.right
  1260. else
  1261. oldroot^.right:=root^.right;
  1262. delete_from_tree:=root;
  1263. end;
  1264. begin
  1265. speedvalue:=getspeedvalue(s);
  1266. n:=root;
  1267. if assigned(hasharray) then
  1268. begin
  1269. {First, check if the node to delete directly located under
  1270. the hasharray.}
  1271. p:=speedvalue mod hasharraysize;
  1272. n:=hasharray^[p];
  1273. if (n<>nil) and (n^.speedvalue=speedvalue) and
  1274. (n^._name^=s) then
  1275. begin
  1276. {The node to delete is directly located under the
  1277. hasharray. Make the hasharray point to the left
  1278. subtree of the node and place the right subtree on
  1279. the right-bottom of the left subtree.}
  1280. if n^.left<>nil then
  1281. begin
  1282. hasharray^[p]:=n^.left;
  1283. if n^.right<>nil then
  1284. insert_right_bottom(n^.left,n^.right);
  1285. end
  1286. else
  1287. hasharray^[p]:=n^.right;
  1288. delete:=n;
  1289. exit;
  1290. end;
  1291. end
  1292. else
  1293. begin
  1294. {First check if the node to delete is the root.}
  1295. if (root<>nil) and (n^.speedvalue=speedvalue)
  1296. and (n^._name^=s) then
  1297. begin
  1298. if n^.left<>nil then
  1299. begin
  1300. root:=n^.left;
  1301. if n^.right<>nil then
  1302. insert_right_bottom(n^.left,n^.right);
  1303. end
  1304. else
  1305. root:=n^.right;
  1306. delete:=n;
  1307. exit;
  1308. end;
  1309. end;
  1310. delete:=delete_from_tree(n);
  1311. end;
  1312. function Tdictionary.empty:boolean;
  1313. var
  1314. w : longint;
  1315. begin
  1316. if assigned(hasharray) then
  1317. begin
  1318. empty:=false;
  1319. for w:=-hasharraysize to hasharraysize do
  1320. if assigned(hasharray^[w]) then
  1321. exit;
  1322. empty:=true;
  1323. end
  1324. else
  1325. empty:=(root=nil);
  1326. end;
  1327. procedure Tdictionary.foreach(proc2call:Tnamedindexcallback);
  1328. procedure a(p:Pnamedindexobject);
  1329. begin
  1330. proc2call(p);
  1331. if assigned(p^.left) then
  1332. a(p^.left);
  1333. if assigned(p^.right) then
  1334. a(p^.right);
  1335. end;
  1336. var
  1337. i : longint;
  1338. begin
  1339. if assigned(hasharray) then
  1340. begin
  1341. for i:=-hasharraysize to hasharraysize do
  1342. if assigned(hasharray^[i]) then
  1343. a(hasharray^[i]);
  1344. end
  1345. else
  1346. if assigned(root) then
  1347. a(root);
  1348. end;
  1349. function Tdictionary.insert(obj:Pnamedindexobject):Pnamedindexobject;
  1350. begin
  1351. obj^.speedvalue:=getspeedvalue(obj^._name^);
  1352. if assigned(hasharray) then
  1353. insert:=insertnode(obj,hasharray^[obj^.speedvalue mod hasharraysize])
  1354. else
  1355. insert:=insertnode(obj,root);
  1356. end;
  1357. function tdictionary.insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  1358. begin
  1359. if currnode=nil then
  1360. begin
  1361. currnode:=newnode;
  1362. insertnode:=newnode;
  1363. end
  1364. { first check speedvalue, to allow a fast insert }
  1365. else
  1366. if currnode^.speedvalue>newnode^.speedvalue then
  1367. insertnode:=insertnode(newnode,currnode^.right)
  1368. else
  1369. if currnode^.speedvalue<newnode^.speedvalue then
  1370. insertnode:=insertnode(newnode,currnode^.left)
  1371. else
  1372. begin
  1373. if currnode^._name^>newnode^._name^ then
  1374. insertnode:=insertnode(newnode,currnode^.right)
  1375. else
  1376. if currnode^._name^<newnode^._name^ then
  1377. insertnode:=insertnode(newnode,currnode^.left)
  1378. else
  1379. begin
  1380. if replace_existing and
  1381. assigned(currnode) then
  1382. begin
  1383. newnode^.left:=currnode^.left;
  1384. newnode^.right:=currnode^.right;
  1385. currnode:=newnode;
  1386. insertnode:=newnode;
  1387. end
  1388. else
  1389. insertnode:=currnode;
  1390. end;
  1391. end;
  1392. end;
  1393. procedure tdictionary.inserttree(currtree,currroot:Pnamedindexobject);
  1394. begin
  1395. if assigned(currtree) then
  1396. begin
  1397. inserttree(currtree^.left,currroot);
  1398. inserttree(currtree^.right,currroot);
  1399. currtree^.right:=nil;
  1400. currtree^.left:=nil;
  1401. insertnode(currtree,currroot);
  1402. end;
  1403. end;
  1404. function tdictionary.rename(const olds,news : string):Pnamedindexobject;
  1405. var
  1406. spdval : longint;
  1407. lasthp,
  1408. hp,hp2,hp3 : Pnamedindexobject;
  1409. begin
  1410. spdval:=getspeedvalue(olds);
  1411. if assigned(hasharray) then
  1412. hp:=hasharray^[spdval mod hasharraysize]
  1413. else
  1414. hp:=root;
  1415. lasthp:=nil;
  1416. while assigned(hp) do
  1417. begin
  1418. if spdval>hp^.speedvalue then
  1419. begin
  1420. lasthp:=hp;
  1421. hp:=hp^.left
  1422. end
  1423. else
  1424. if spdval<hp^.speedvalue then
  1425. begin
  1426. lasthp:=hp;
  1427. hp:=hp^.right
  1428. end
  1429. else
  1430. begin
  1431. if (hp^.name=olds) then
  1432. begin
  1433. { get in hp2 the replacer for the root or hasharr }
  1434. hp2:=hp^.left;
  1435. hp3:=hp^.right;
  1436. if not assigned(hp2) then
  1437. begin
  1438. hp2:=hp^.right;
  1439. hp3:=hp^.left;
  1440. end;
  1441. { remove entry from the tree }
  1442. if assigned(lasthp) then
  1443. begin
  1444. if lasthp^.left=hp then
  1445. lasthp^.left:=hp2
  1446. else
  1447. lasthp^.right:=hp2;
  1448. end
  1449. else
  1450. begin
  1451. if assigned(hasharray) then
  1452. hasharray^[spdval mod hasharraysize]:=hp2
  1453. else
  1454. root:=hp2;
  1455. end;
  1456. { reinsert the hp3 in the tree from hp2 }
  1457. inserttree(hp3,hp2);
  1458. { reset node with new values }
  1459. stringdispose(hp^._name);
  1460. hp^._name:=stringdup(news);
  1461. hp^.speedvalue:=getspeedvalue(news);
  1462. hp^.left:=nil;
  1463. hp^.right:=nil;
  1464. { reinsert }
  1465. if assigned(hasharray) then
  1466. rename:=insertnode(hp,hasharray^[hp^.speedvalue mod hasharraysize])
  1467. else
  1468. rename:=insertnode(hp,root);
  1469. exit;
  1470. end
  1471. else
  1472. if olds>hp^.name then
  1473. begin
  1474. lasthp:=hp;
  1475. hp:=hp^.left
  1476. end
  1477. else
  1478. begin
  1479. lasthp:=hp;
  1480. hp:=hp^.right;
  1481. end;
  1482. end;
  1483. end;
  1484. end;
  1485. function Tdictionary.search(const s:string):Pnamedindexobject;
  1486. begin
  1487. search:=speedsearch(s,getspeedvalue(s));
  1488. end;
  1489. function Tdictionary.speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  1490. var
  1491. newnode:Pnamedindexobject;
  1492. begin
  1493. if assigned(hasharray) then
  1494. newnode:=hasharray^[speedvalue mod hasharraysize]
  1495. else
  1496. newnode:=root;
  1497. while assigned(newnode) do
  1498. begin
  1499. if speedvalue>newnode^.speedvalue then
  1500. newnode:=newnode^.left
  1501. else
  1502. if speedvalue<newnode^.speedvalue then
  1503. newnode:=newnode^.right
  1504. else
  1505. begin
  1506. if (newnode^._name^=s) then
  1507. begin
  1508. speedsearch:=newnode;
  1509. exit;
  1510. end
  1511. else
  1512. if s>newnode^._name^ then
  1513. newnode:=newnode^.left
  1514. else
  1515. newnode:=newnode^.right;
  1516. end;
  1517. end;
  1518. speedsearch:=nil;
  1519. end;
  1520. {****************************************************************************
  1521. tsinglelist
  1522. ****************************************************************************}
  1523. constructor tsinglelist.init;
  1524. begin
  1525. first:=nil;
  1526. last:=nil;
  1527. noclear:=false;
  1528. end;
  1529. destructor tsinglelist.done;
  1530. begin
  1531. if not noclear then
  1532. clear;
  1533. end;
  1534. procedure tsinglelist.clear;
  1535. var
  1536. hp,hp2 : pnamedindexobject;
  1537. begin
  1538. hp:=first;
  1539. while assigned(hp) do
  1540. begin
  1541. hp2:=hp;
  1542. hp:=hp^.listnext;
  1543. dispose(hp2,done);
  1544. end;
  1545. first:=nil;
  1546. last:=nil;
  1547. end;
  1548. procedure tsinglelist.insert(p:Pnamedindexobject);
  1549. begin
  1550. if not assigned(first) then
  1551. first:=p
  1552. else
  1553. last^.listnext:=p;
  1554. last:=p;
  1555. p^.listnext:=nil;
  1556. end;
  1557. {****************************************************************************
  1558. tdynamicarray
  1559. ****************************************************************************}
  1560. constructor tdynamicarray.init(Ablocksize:longint);
  1561. begin
  1562. posn:=0;
  1563. posnblock:=nil;
  1564. firstblock:=nil;
  1565. lastblock:=nil;
  1566. blocksize:=Ablocksize;
  1567. grow;
  1568. end;
  1569. function tdynamicarray.size:longint;
  1570. begin
  1571. if assigned(lastblock) then
  1572. size:=lastblock^.pos+lastblock^.used
  1573. else
  1574. size:=0;
  1575. end;
  1576. procedure tdynamicarray.grow;
  1577. var
  1578. nblock : pdynamicblock;
  1579. begin
  1580. getmem(nblock,blocksize+dynamicblockbasesize);
  1581. if not assigned(firstblock) then
  1582. begin
  1583. firstblock:=nblock;
  1584. posnblock:=nblock;
  1585. nblock^.pos:=0;
  1586. end
  1587. else
  1588. begin
  1589. lastblock^.next:=nblock;
  1590. nblock^.pos:=lastblock^.pos+lastblock^.used;
  1591. end;
  1592. nblock^.used:=0;
  1593. nblock^.next:=nil;
  1594. fillchar(nblock^.data,blocksize,0);
  1595. lastblock:=nblock;
  1596. end;
  1597. procedure tdynamicarray.align(i:longint);
  1598. var
  1599. j : longint;
  1600. begin
  1601. j:=(posn mod i);
  1602. if j<>0 then
  1603. begin
  1604. j:=i-j;
  1605. if posnblock^.used+j>blocksize then
  1606. begin
  1607. posnblock^.used:=blocksize;
  1608. dec(j,blocksize-posnblock^.used);
  1609. grow;
  1610. posnblock:=lastblock;
  1611. end;
  1612. inc(posnblock^.used,j);
  1613. inc(posn,j);
  1614. end;
  1615. end;
  1616. procedure tdynamicarray.seek(i:longint);
  1617. begin
  1618. if (i<posnblock^.pos) or (i>posnblock^.pos+blocksize) then
  1619. begin
  1620. { set posnblock correct if the size is bigger then
  1621. the current block }
  1622. if posnblock^.pos>i then
  1623. posnblock:=firstblock;
  1624. while assigned(posnblock) do
  1625. begin
  1626. if posnblock^.pos+blocksize>i then
  1627. break;
  1628. posnblock:=posnblock^.next;
  1629. end;
  1630. { not found ? then increase blocks }
  1631. if not assigned(posnblock) then
  1632. begin
  1633. { the current lastblock is now also fully used }
  1634. lastblock^.used:=blocksize;
  1635. repeat
  1636. grow;
  1637. posnblock:=lastblock;
  1638. until posnblock^.pos+blocksize>=i;
  1639. end;
  1640. end;
  1641. posn:=i;
  1642. if posn mod blocksize>posnblock^.used then
  1643. posnblock^.used:=posn mod blocksize;
  1644. end;
  1645. procedure tdynamicarray.write(var d;len:longint);
  1646. var
  1647. p : pchar;
  1648. i,j : longint;
  1649. begin
  1650. p:=pchar(@d);
  1651. while (len>0) do
  1652. begin
  1653. i:=posn mod blocksize;
  1654. if i+len>=blocksize then
  1655. begin
  1656. j:=blocksize-i;
  1657. move(p^,posnblock^.data[i],j);
  1658. inc(p,j);
  1659. inc(posn,j);
  1660. dec(len,j);
  1661. posnblock^.used:=blocksize;
  1662. if assigned(posnblock^.next) then
  1663. posnblock:=posnblock^.next
  1664. else
  1665. begin
  1666. grow;
  1667. posnblock:=lastblock;
  1668. end;
  1669. end
  1670. else
  1671. begin
  1672. move(p^,posnblock^.data[i],len);
  1673. inc(p,len);
  1674. inc(posn,len);
  1675. i:=posn mod blocksize;
  1676. if i>posnblock^.used then
  1677. posnblock^.used:=i;
  1678. len:=0;
  1679. end;
  1680. end;
  1681. end;
  1682. function tdynamicarray.read(var d;len:longint):longint;
  1683. var
  1684. p : pchar;
  1685. i,j,res : longint;
  1686. begin
  1687. res:=0;
  1688. p:=pchar(@d);
  1689. while (len>0) do
  1690. begin
  1691. i:=posn mod blocksize;
  1692. if i+len>=posnblock^.used then
  1693. begin
  1694. j:=posnblock^.used-i;
  1695. move(posnblock^.data[i],p^,j);
  1696. inc(p,j);
  1697. inc(posn,j);
  1698. inc(res,j);
  1699. dec(len,j);
  1700. if assigned(posnblock^.next) then
  1701. posnblock:=posnblock^.next
  1702. else
  1703. break;
  1704. end
  1705. else
  1706. begin
  1707. move(posnblock^.data[i],p^,len);
  1708. inc(p,len);
  1709. inc(posn,len);
  1710. inc(res,len);
  1711. len:=0;
  1712. end;
  1713. end;
  1714. read:=res;
  1715. end;
  1716. procedure tdynamicarray.blockwrite(var f:file);
  1717. var
  1718. hp : pdynamicblock;
  1719. begin
  1720. hp:=firstblock;
  1721. while assigned(hp) do
  1722. begin
  1723. system.blockwrite(f,hp^.data,hp^.used);
  1724. hp:=hp^.next;
  1725. end;
  1726. end;
  1727. destructor tdynamicarray.done;
  1728. var
  1729. hp : pdynamicblock;
  1730. begin
  1731. while assigned(firstblock) do
  1732. begin
  1733. hp:=firstblock;
  1734. firstblock:=firstblock^.next;
  1735. freemem(hp,blocksize+dynamicblockbasesize);
  1736. end;
  1737. end;
  1738. {****************************************************************************
  1739. tindexarray
  1740. ****************************************************************************}
  1741. constructor tindexarray.init(Agrowsize:longint);
  1742. begin
  1743. growsize:=Agrowsize;
  1744. size:=0;
  1745. count:=0;
  1746. data:=nil;
  1747. first:=nil;
  1748. noclear:=false;
  1749. end;
  1750. destructor tindexarray.done;
  1751. begin
  1752. if assigned(data) then
  1753. begin
  1754. if not noclear then
  1755. clear;
  1756. freemem(data,size*4);
  1757. data:=nil;
  1758. end;
  1759. end;
  1760. function tindexarray.search(nr:longint):Pnamedindexobject;
  1761. begin
  1762. if nr<=count then
  1763. search:=data^[nr]
  1764. else
  1765. search:=nil;
  1766. end;
  1767. procedure tindexarray.clear;
  1768. var
  1769. i : longint;
  1770. begin
  1771. for i:=1 to count do
  1772. if assigned(data^[i]) then
  1773. begin
  1774. dispose(data^[i],done);
  1775. data^[i]:=nil;
  1776. end;
  1777. count:=0;
  1778. first:=nil;
  1779. end;
  1780. procedure tindexarray.foreach(proc2call : Tnamedindexcallback);
  1781. var
  1782. i : longint;
  1783. begin
  1784. for i:=1 to count do
  1785. if assigned(data^[i]) then
  1786. proc2call(data^[i]);
  1787. end;
  1788. procedure tindexarray.grow(gsize:longint);
  1789. var
  1790. osize : longint;
  1791. {$ifndef USEREALLOCMEM}
  1792. odata : Pnamedindexobjectarray;
  1793. {$endif USEREALLOCMEM}
  1794. begin
  1795. osize:=size;
  1796. inc(size,gsize);
  1797. {$ifndef USEREALLOCMEM}
  1798. odata:=data;
  1799. getmem(data,size*4);
  1800. if assigned(odata) then
  1801. begin
  1802. move(odata^,data^,osize*4);
  1803. freemem(odata,osize*4);
  1804. end;
  1805. {$else USEREALLOCMEM}
  1806. reallocmem(data,size*4);
  1807. {$endif USEREALLOCMEM}
  1808. fillchar(data^[osize+1],gsize*4,0);
  1809. end;
  1810. procedure tindexarray.deleteindex(p:Pnamedindexobject);
  1811. var
  1812. i : longint;
  1813. begin
  1814. i:=p^.indexnr;
  1815. { update counter }
  1816. if i=count then
  1817. dec(count);
  1818. { update linked list }
  1819. while (i>0) do
  1820. begin
  1821. dec(i);
  1822. if (i>0) and assigned(data^[i]) then
  1823. begin
  1824. data^[i]^.indexnext:=data^[p^.indexnr]^.indexnext;
  1825. break;
  1826. end;
  1827. end;
  1828. if i=0 then
  1829. first:=p^.indexnext;
  1830. data^[p^.indexnr]:=nil;
  1831. { clear entry }
  1832. p^.indexnr:=-1;
  1833. p^.indexnext:=nil;
  1834. end;
  1835. procedure tindexarray.delete(p:Pnamedindexobject);
  1836. begin
  1837. deleteindex(p);
  1838. dispose(p,done);
  1839. p:=nil;
  1840. end;
  1841. procedure tindexarray.insert(p:Pnamedindexobject);
  1842. var
  1843. i : longint;
  1844. begin
  1845. if p^.indexnr=-1 then
  1846. begin
  1847. inc(count);
  1848. p^.indexnr:=count;
  1849. end;
  1850. if p^.indexnr>count then
  1851. count:=p^.indexnr;
  1852. if count>size then
  1853. grow(((count div growsize)+1)*growsize);
  1854. data^[p^.indexnr]:=p;
  1855. { update linked list backward }
  1856. i:=p^.indexnr;
  1857. while (i>0) do
  1858. begin
  1859. dec(i);
  1860. if (i>0) and assigned(data^[i]) then
  1861. begin
  1862. data^[i]^.indexnext:=p;
  1863. break;
  1864. end;
  1865. end;
  1866. if i=0 then
  1867. first:=p;
  1868. { update linked list forward }
  1869. i:=p^.indexnr;
  1870. while (i<=count) do
  1871. begin
  1872. inc(i);
  1873. if (i<=count) and assigned(data^[i]) then
  1874. begin
  1875. p^.indexnext:=data^[i];
  1876. exit;
  1877. end;
  1878. end;
  1879. if i>count then
  1880. p^.indexnext:=nil;
  1881. end;
  1882. {$ifdef BUFFEREDFILE}
  1883. {****************************************************************************
  1884. TBUFFEREDFILE
  1885. ****************************************************************************}
  1886. Const
  1887. crcseed = $ffffffff;
  1888. crctable : array[0..255] of longint = (
  1889. $00000000,$77073096,$ee0e612c,$990951ba,$076dc419,$706af48f,
  1890. $e963a535,$9e6495a3,$0edb8832,$79dcb8a4,$e0d5e91e,$97d2d988,
  1891. $09b64c2b,$7eb17cbd,$e7b82d07,$90bf1d91,$1db71064,$6ab020f2,
  1892. $f3b97148,$84be41de,$1adad47d,$6ddde4eb,$f4d4b551,$83d385c7,
  1893. $136c9856,$646ba8c0,$fd62f97a,$8a65c9ec,$14015c4f,$63066cd9,
  1894. $fa0f3d63,$8d080df5,$3b6e20c8,$4c69105e,$d56041e4,$a2677172,
  1895. $3c03e4d1,$4b04d447,$d20d85fd,$a50ab56b,$35b5a8fa,$42b2986c,
  1896. $dbbbc9d6,$acbcf940,$32d86ce3,$45df5c75,$dcd60dcf,$abd13d59,
  1897. $26d930ac,$51de003a,$c8d75180,$bfd06116,$21b4f4b5,$56b3c423,
  1898. $cfba9599,$b8bda50f,$2802b89e,$5f058808,$c60cd9b2,$b10be924,
  1899. $2f6f7c87,$58684c11,$c1611dab,$b6662d3d,$76dc4190,$01db7106,
  1900. $98d220bc,$efd5102a,$71b18589,$06b6b51f,$9fbfe4a5,$e8b8d433,
  1901. $7807c9a2,$0f00f934,$9609a88e,$e10e9818,$7f6a0dbb,$086d3d2d,
  1902. $91646c97,$e6635c01,$6b6b51f4,$1c6c6162,$856530d8,$f262004e,
  1903. $6c0695ed,$1b01a57b,$8208f4c1,$f50fc457,$65b0d9c6,$12b7e950,
  1904. $8bbeb8ea,$fcb9887c,$62dd1ddf,$15da2d49,$8cd37cf3,$fbd44c65,
  1905. $4db26158,$3ab551ce,$a3bc0074,$d4bb30e2,$4adfa541,$3dd895d7,
  1906. $a4d1c46d,$d3d6f4fb,$4369e96a,$346ed9fc,$ad678846,$da60b8d0,
  1907. $44042d73,$33031de5,$aa0a4c5f,$dd0d7cc9,$5005713c,$270241aa,
  1908. $be0b1010,$c90c2086,$5768b525,$206f85b3,$b966d409,$ce61e49f,
  1909. $5edef90e,$29d9c998,$b0d09822,$c7d7a8b4,$59b33d17,$2eb40d81,
  1910. $b7bd5c3b,$c0ba6cad,$edb88320,$9abfb3b6,$03b6e20c,$74b1d29a,
  1911. $ead54739,$9dd277af,$04db2615,$73dc1683,$e3630b12,$94643b84,
  1912. $0d6d6a3e,$7a6a5aa8,$e40ecf0b,$9309ff9d,$0a00ae27,$7d079eb1,
  1913. $f00f9344,$8708a3d2,$1e01f268,$6906c2fe,$f762575d,$806567cb,
  1914. $196c3671,$6e6b06e7,$fed41b76,$89d32be0,$10da7a5a,$67dd4acc,
  1915. $f9b9df6f,$8ebeeff9,$17b7be43,$60b08ed5,$d6d6a3e8,$a1d1937e,
  1916. $38d8c2c4,$4fdff252,$d1bb67f1,$a6bc5767,$3fb506dd,$48b2364b,
  1917. $d80d2bda,$af0a1b4c,$36034af6,$41047a60,$df60efc3,$a867df55,
  1918. $316e8eef,$4669be79,$cb61b38c,$bc66831a,$256fd2a0,$5268e236,
  1919. $cc0c7795,$bb0b4703,$220216b9,$5505262f,$c5ba3bbe,$b2bd0b28,
  1920. $2bb45a92,$5cb36a04,$c2d7ffa7,$b5d0cf31,$2cd99e8b,$5bdeae1d,
  1921. $9b64c2b0,$ec63f226,$756aa39c,$026d930a,$9c0906a9,$eb0e363f,
  1922. $72076785,$05005713,$95bf4a82,$e2b87a14,$7bb12bae,$0cb61b38,
  1923. $92d28e9b,$e5d5be0d,$7cdcefb7,$0bdbdf21,$86d3d2d4,$f1d4e242,
  1924. $68ddb3f8,$1fda836e,$81be16cd,$f6b9265b,$6fb077e1,$18b74777,
  1925. $88085ae6,$ff0f6a70,$66063bca,$11010b5c,$8f659eff,$f862ae69,
  1926. $616bffd3,$166ccf45,$a00ae278,$d70dd2ee,$4e048354,$3903b3c2,
  1927. $a7672661,$d06016f7,$4969474d,$3e6e77db,$aed16a4a,$d9d65adc,
  1928. $40df0b66,$37d83bf0,$a9bcae53,$debb9ec5,$47b2cf7f,$30b5ffe9,
  1929. $bdbdf21c,$cabac28a,$53b39330,$24b4a3a6,$bad03605,$cdd70693,
  1930. $54de5729,$23d967bf,$b3667a2e,$c4614ab8,$5d681b02,$2a6f2b94,
  1931. $b40bbe37,$c30c8ea1,$5a05df1b,$2d02ef8d);
  1932. constructor tbufferedfile.init(const filename : string;_bufsize : longint);
  1933. begin
  1934. assign(f,filename);
  1935. bufsize:=_bufsize;
  1936. bufpos:=0;
  1937. buflast:=0;
  1938. do_crc:=false;
  1939. iomode:=0;
  1940. tempclosed:=false;
  1941. change_endian:=false;
  1942. clear_crc;
  1943. end;
  1944. destructor tbufferedfile.done;
  1945. begin
  1946. close;
  1947. end;
  1948. procedure tbufferedfile.clear_crc;
  1949. begin
  1950. crc:=crcseed;
  1951. end;
  1952. procedure tbufferedfile.setbuf(p : pchar;s : longint);
  1953. begin
  1954. flush;
  1955. freemem(buf,bufsize);
  1956. bufsize:=s;
  1957. buf:=p;
  1958. end;
  1959. function tbufferedfile.reset:boolean;
  1960. var
  1961. ofm : byte;
  1962. begin
  1963. ofm:=filemode;
  1964. iomode:=1;
  1965. getmem(buf,bufsize);
  1966. filemode:=0;
  1967. {$I-}
  1968. system.reset(f,1);
  1969. {$I+}
  1970. reset:=(ioresult=0);
  1971. filemode:=ofm;
  1972. end;
  1973. procedure tbufferedfile.rewrite;
  1974. begin
  1975. iomode:=2;
  1976. getmem(buf,bufsize);
  1977. system.rewrite(f,1);
  1978. end;
  1979. procedure tbufferedfile.flush;
  1980. var
  1981. {$ifdef FPC}
  1982. count : longint;
  1983. {$else}
  1984. count : integer;
  1985. {$endif}
  1986. begin
  1987. if iomode=2 then
  1988. begin
  1989. if bufpos=0 then
  1990. exit;
  1991. blockwrite(f,buf^,bufpos)
  1992. end
  1993. else if iomode=1 then
  1994. if buflast=bufpos then
  1995. begin
  1996. blockread(f,buf^,bufsize,count);
  1997. buflast:=count;
  1998. end;
  1999. bufpos:=0;
  2000. end;
  2001. function tbufferedfile.getftime : longint;
  2002. var
  2003. l : longint;
  2004. {$ifdef linux}
  2005. Info : Stat;
  2006. {$endif}
  2007. begin
  2008. {$ifndef linux}
  2009. { this only works if the file is open !! }
  2010. dos.getftime(f,l);
  2011. {$else}
  2012. Fstat(f,Info);
  2013. l:=info.mtime;
  2014. {$endif}
  2015. getftime:=l;
  2016. end;
  2017. function tbufferedfile.getsize : longint;
  2018. begin
  2019. getsize:=filesize(f);
  2020. end;
  2021. procedure tbufferedfile.seek(l : longint);
  2022. begin
  2023. if iomode=2 then
  2024. begin
  2025. flush;
  2026. system.seek(f,l);
  2027. end
  2028. else if iomode=1 then
  2029. begin
  2030. { forces a reload }
  2031. bufpos:=buflast;
  2032. system.seek(f,l);
  2033. flush;
  2034. end;
  2035. end;
  2036. type
  2037. {$ifdef tp}
  2038. bytearray1 = array [1..65535] of byte;
  2039. {$else}
  2040. bytearray1 = array [1..10000000] of byte;
  2041. {$endif}
  2042. procedure tbufferedfile.read_data(var data;bytes : longint;var count : longint);
  2043. var
  2044. p : pchar;
  2045. c,i : longint;
  2046. begin
  2047. p:=pchar(@data);
  2048. count:=0;
  2049. while bytes-count>0 do
  2050. begin
  2051. if bytes-count>buflast-bufpos then
  2052. begin
  2053. move((buf+bufpos)^,(p+count)^,buflast-bufpos);
  2054. inc(count,buflast-bufpos);
  2055. bufpos:=buflast;
  2056. flush;
  2057. { can't we read anything ? }
  2058. if bufpos=buflast then
  2059. break;
  2060. end
  2061. else
  2062. begin
  2063. move((buf+bufpos)^,(p+count)^,bytes-count);
  2064. inc(bufpos,bytes-count);
  2065. count:=bytes;
  2066. break;
  2067. end;
  2068. end;
  2069. if do_crc then
  2070. begin
  2071. c:=crc;
  2072. for i:=1 to bytes do
  2073. c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  2074. crc:=c;
  2075. end;
  2076. end;
  2077. procedure tbufferedfile.write_data(var data;count : longint);
  2078. var
  2079. c,i : longint;
  2080. begin
  2081. if bufpos+count>bufsize then
  2082. flush;
  2083. move(data,(buf+bufpos)^,count);
  2084. inc(bufpos,count);
  2085. if do_crc then
  2086. begin
  2087. c:=crc;
  2088. for i:=1 to count do
  2089. c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  2090. crc:=c;
  2091. end;
  2092. end;
  2093. function tbufferedfile.getcrc : longint;
  2094. begin
  2095. getcrc:=crc xor crcseed;
  2096. end;
  2097. procedure tbufferedfile.write_string(const s : string);
  2098. begin
  2099. if bufpos+length(s)>bufsize then
  2100. flush;
  2101. { why is there not CRC here ??? }
  2102. move(s[1],(buf+bufpos)^,length(s));
  2103. inc(bufpos,length(s));
  2104. { should be
  2105. write_data(s[1],length(s)); }
  2106. end;
  2107. procedure tbufferedfile.write_pchar(p : pchar);
  2108. var
  2109. l : longint;
  2110. begin
  2111. l:=strlen(p);
  2112. if l>=bufsize then
  2113. do_internalerror(222);
  2114. { why is there not CRC here ???}
  2115. if bufpos+l>bufsize then
  2116. flush;
  2117. move(p^,(buf+bufpos)^,l);
  2118. inc(bufpos,l);
  2119. { should be
  2120. write_data(p^,l); }
  2121. end;
  2122. procedure tbufferedfile.write_byte(b : byte);
  2123. begin
  2124. write_data(b,sizeof(byte));
  2125. end;
  2126. procedure tbufferedfile.write_long(l : longint);
  2127. var
  2128. w1,w2 : word;
  2129. begin
  2130. if change_endian then
  2131. begin
  2132. w1:=l and $ffff;
  2133. w2:=l shr 16;
  2134. l:=swap(w2)+(longint(swap(w1)) shl 16);
  2135. end;
  2136. write_data(l,sizeof(longint));
  2137. end;
  2138. procedure tbufferedfile.write_word(w : word);
  2139. begin
  2140. if change_endian then
  2141. begin
  2142. w:=swap(w);
  2143. end;
  2144. write_data(w,sizeof(word));
  2145. end;
  2146. procedure tbufferedfile.write_double(d : double);
  2147. begin
  2148. write_data(d,sizeof(double));
  2149. end;
  2150. function tbufferedfile.getpath : string;
  2151. begin
  2152. {$ifdef dummy}
  2153. getpath:=strpas(filerec(f).name);
  2154. {$endif}
  2155. getpath:='';
  2156. end;
  2157. procedure tbufferedfile.close;
  2158. begin
  2159. if iomode<>0 then
  2160. begin
  2161. flush;
  2162. system.close(f);
  2163. freemem(buf,bufsize);
  2164. buf:=nil;
  2165. iomode:=0;
  2166. end;
  2167. end;
  2168. procedure tbufferedfile.tempclose;
  2169. begin
  2170. if iomode<>0 then
  2171. begin
  2172. temppos:=system.filepos(f);
  2173. tempmode:=iomode;
  2174. tempclosed:=true;
  2175. system.close(f);
  2176. iomode:=0;
  2177. end
  2178. else
  2179. tempclosed:=false;
  2180. end;
  2181. procedure tbufferedfile.tempreopen;
  2182. var
  2183. ofm : byte;
  2184. begin
  2185. if tempclosed then
  2186. begin
  2187. case tempmode of
  2188. 1 : begin
  2189. ofm:=filemode;
  2190. iomode:=1;
  2191. filemode:=0;
  2192. system.reset(f,1);
  2193. filemode:=ofm;
  2194. end;
  2195. 2 : begin
  2196. iomode:=2;
  2197. system.rewrite(f,1);
  2198. end;
  2199. end;
  2200. system.seek(f,temppos);
  2201. tempclosed:=false;
  2202. end;
  2203. end;
  2204. {$endif BUFFEREDFILE}
  2205. end.
  2206. {
  2207. $Log$
  2208. Revision 1.10 2000-08-19 18:44:27 peter
  2209. * new tdynamicarray implementation using blocks instead of
  2210. reallocmem (merged)
  2211. Revision 1.9 2000/08/16 18:33:53 peter
  2212. * splitted namedobjectitem.next into indexnext and listnext so it
  2213. can be used in both lists
  2214. * don't allow "word = word" type definitions (merged)
  2215. Revision 1.8 2000/08/13 08:41:57 peter
  2216. * fixed typo in tsinglelist.clear (merged)
  2217. Revision 1.7 2000/08/12 15:34:22 peter
  2218. + usedasmsymbollist to check and reset only the used symbols (merged)
  2219. Revision 1.6 2000/08/10 12:20:44 jonas
  2220. * reallocmem is now also used under Delphi (merged from fixes branch)
  2221. Revision 1.5 2000/08/09 12:09:45 jonas
  2222. * tidexarray and tdynamicarray now use reallocmem() under FPC for
  2223. growing (merged from fixes branch)
  2224. Revision 1.4 2000/08/06 19:42:40 peter
  2225. * removed note
  2226. Revision 1.3 2000/08/02 19:49:58 peter
  2227. * first things for default parameters
  2228. Revision 1.2 2000/07/13 11:32:38 michael
  2229. + removed logs
  2230. }