cutils.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. {
  2. $Id$
  3. Copyright (C) 1998-2000 by Florian Klaempfl
  4. This unit implements some support functions
  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+}
  20. {$endif}
  21. unit cutils;
  22. interface
  23. type
  24. pstring = ^string;
  25. {$ifdef TP}
  26. { redeclare dword only in case of emergency, some small things
  27. of the compiler won't work then correctly (FK)
  28. }
  29. dword = longint;
  30. {$endif TP}
  31. function min(a,b : longint) : longint;
  32. function max(a,b : longint) : longint;
  33. function align(i,a:longint):longint;
  34. function align_from_size(datasize:longint;length:longint):longint;
  35. procedure Replace(var s:string;s1:string;const s2:string);
  36. procedure ReplaceCase(var s:string;const s1,s2:string);
  37. function upper(const s : string) : string;
  38. function lower(const s : string) : string;
  39. function trimspace(const s:string):string;
  40. procedure uppervar(var s : string);
  41. function hexstr(val : longint;cnt : byte) : string;
  42. {$ifdef FPC}
  43. function tostru(i:cardinal) : string;
  44. {$else}
  45. function tostru(i:longint) : string;
  46. {$endif}
  47. function tostr(i : longint) : string;
  48. function tostr_with_plus(i : longint) : string;
  49. procedure valint(S : string;var V : longint;var code : integer);
  50. function is_number(const s : string) : boolean;
  51. function ispowerof2(value : longint;var power : longint) : boolean;
  52. { releases the string p and assignes nil to p }
  53. { if p=nil then freemem isn't called }
  54. procedure stringdispose(var p : pstring);
  55. { allocates mem for a copy of s, copies s to this mem and returns }
  56. { a pointer to this mem }
  57. function stringdup(const s : string) : pstring;
  58. { allocates memory for s and copies s as zero terminated string
  59. to that mem and returns a pointer to that mem }
  60. function strpnew(const s : string) : pchar;
  61. procedure strdispose(var p : pchar);
  62. { makes a char lowercase, with spanish, french and german char set }
  63. function lowercase(c : char) : char;
  64. { makes zero terminated string to a pascal string }
  65. { the data in p is modified and p is returned }
  66. function pchar2pstring(p : pchar) : pstring;
  67. { ambivalent to pchar2pstring }
  68. function pstring2pchar(p : pstring) : pchar;
  69. { Speed/Hash value }
  70. function getspeedvalue(const s : string) : longint;
  71. { Ansistring (pchar+length) support }
  72. procedure ansistringdispose(var p : pchar;length : longint);
  73. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  74. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  75. implementation
  76. uses
  77. strings;
  78. function min(a,b : longint) : longint;
  79. {
  80. return the minimal of a and b
  81. }
  82. begin
  83. if a>b then
  84. min:=b
  85. else
  86. min:=a;
  87. end;
  88. function max(a,b : longint) : longint;
  89. {
  90. return the maximum of a and b
  91. }
  92. begin
  93. if a<b then
  94. max:=b
  95. else
  96. max:=a;
  97. end;
  98. function align_from_size(datasize:longint;length:longint):longint;
  99. {Increases the datasize with the required alignment; i.e. on pentium
  100. words should be aligned word; and dwords should be aligned dword.
  101. So for a word (len=2), datasize is increased to the nearest multiple
  102. of 2, and for len=4, datasize is increased to the nearest multiple of
  103. 4.}
  104. var data_align:word;
  105. begin
  106. {$IFDEF I386}
  107. if length>2 then
  108. data_align:=4
  109. else if length>1 then
  110. data_align:=2
  111. else
  112. data_align:=1;
  113. {$ENDIF}
  114. {$IFDEF M68K}
  115. data_align:=2;
  116. {$ENDIF}
  117. align_from_size:=(datasize+data_align-1) and not(data_align-1);
  118. end;
  119. function align(i,a:longint):longint;
  120. {
  121. return value <i> aligned <a> boundary
  122. }
  123. begin
  124. { for 0 and 1 no aligning is needed }
  125. if a<=1 then
  126. align:=i
  127. else
  128. align:=(i+a-1) and not(a-1);
  129. end;
  130. procedure Replace(var s:string;s1:string;const s2:string);
  131. var
  132. last,
  133. i : longint;
  134. begin
  135. s1:=upper(s1);
  136. last:=0;
  137. repeat
  138. i:=pos(s1,upper(s));
  139. if i=last then
  140. i:=0;
  141. if (i>0) then
  142. begin
  143. Delete(s,i,length(s1));
  144. Insert(s2,s,i);
  145. last:=i;
  146. end;
  147. until (i=0);
  148. end;
  149. procedure ReplaceCase(var s:string;const s1,s2:string);
  150. var
  151. last,
  152. i : longint;
  153. begin
  154. last:=0;
  155. repeat
  156. i:=pos(s1,s);
  157. if i=last then
  158. i:=0;
  159. if (i>0) then
  160. begin
  161. Delete(s,i,length(s1));
  162. Insert(s2,s,i);
  163. last:=i;
  164. end;
  165. until (i=0);
  166. end;
  167. function upper(const s : string) : string;
  168. {
  169. return uppercased string of s
  170. }
  171. var
  172. i : longint;
  173. begin
  174. for i:=1 to length(s) do
  175. if s[i] in ['a'..'z'] then
  176. upper[i]:=char(byte(s[i])-32)
  177. else
  178. upper[i]:=s[i];
  179. upper[0]:=s[0];
  180. end;
  181. function lower(const s : string) : string;
  182. {
  183. return lowercased string of s
  184. }
  185. var
  186. i : longint;
  187. begin
  188. for i:=1 to length(s) do
  189. if s[i] in ['A'..'Z'] then
  190. lower[i]:=char(byte(s[i])+32)
  191. else
  192. lower[i]:=s[i];
  193. lower[0]:=s[0];
  194. end;
  195. procedure uppervar(var s : string);
  196. {
  197. uppercase string s
  198. }
  199. var
  200. i : longint;
  201. begin
  202. for i:=1 to length(s) do
  203. if s[i] in ['a'..'z'] then
  204. s[i]:=char(byte(s[i])-32);
  205. end;
  206. function hexstr(val : longint;cnt : byte) : string;
  207. const
  208. HexTbl : array[0..15] of char='0123456789ABCDEF';
  209. var
  210. i : longint;
  211. begin
  212. hexstr[0]:=char(cnt);
  213. for i:=cnt downto 1 do
  214. begin
  215. hexstr[i]:=hextbl[val and $f];
  216. val:=val shr 4;
  217. end;
  218. end;
  219. {$ifdef FPC}
  220. function tostru(i:cardinal):string;
  221. {
  222. return string of value i, but for cardinals
  223. }
  224. var
  225. hs : string;
  226. begin
  227. str(i,hs);
  228. tostru:=hs;
  229. end;
  230. {$else FPC}
  231. function tostru(i:longint):string;
  232. begin
  233. tostru:=tostr(i);
  234. end;
  235. {$endif FPC}
  236. function trimspace(const s:string):string;
  237. {
  238. return s with all leading and ending spaces and tabs removed
  239. }
  240. var
  241. i,j : longint;
  242. begin
  243. i:=length(s);
  244. while (i>0) and (s[i] in [#9,' ']) do
  245. dec(i);
  246. j:=1;
  247. while (j<i) and (s[j] in [#9,' ']) do
  248. inc(j);
  249. trimspace:=Copy(s,j,i-j+1);
  250. end;
  251. function tostr(i : longint) : string;
  252. {
  253. return string of value i
  254. }
  255. var
  256. hs : string;
  257. begin
  258. str(i,hs);
  259. tostr:=hs;
  260. end;
  261. function tostr_with_plus(i : longint) : string;
  262. {
  263. return string of value i, but always include a + when i>=0
  264. }
  265. var
  266. hs : string;
  267. begin
  268. str(i,hs);
  269. if i>=0 then
  270. tostr_with_plus:='+'+hs
  271. else
  272. tostr_with_plus:=hs;
  273. end;
  274. procedure valint(S : string;var V : longint;var code : integer);
  275. {
  276. val() with support for octal, which is not supported under tp7
  277. }
  278. {$ifndef FPC}
  279. var
  280. vs : longint;
  281. c : byte;
  282. begin
  283. if s[1]='%' then
  284. begin
  285. vs:=0;
  286. longint(v):=0;
  287. for c:=2 to length(s) do
  288. begin
  289. if s[c]='0' then
  290. vs:=vs shl 1
  291. else
  292. if s[c]='1' then
  293. vs:=vs shl 1+1
  294. else
  295. begin
  296. code:=c;
  297. exit;
  298. end;
  299. end;
  300. code:=0;
  301. longint(v):=vs;
  302. end
  303. else
  304. system.val(S,V,code);
  305. end;
  306. {$else not FPC}
  307. begin
  308. system.val(S,V,code);
  309. end;
  310. {$endif not FPC}
  311. function is_number(const s : string) : boolean;
  312. {
  313. is string a correct number ?
  314. }
  315. var
  316. w : integer;
  317. l : longint;
  318. begin
  319. valint(s,l,w);
  320. is_number:=(w=0);
  321. end;
  322. function ispowerof2(value : longint;var power : longint) : boolean;
  323. {
  324. return if value is a power of 2. And if correct return the power
  325. }
  326. var
  327. hl : longint;
  328. i : longint;
  329. begin
  330. hl:=1;
  331. ispowerof2:=true;
  332. for i:=0 to 31 do
  333. begin
  334. if hl=value then
  335. begin
  336. power:=i;
  337. exit;
  338. end;
  339. hl:=hl shl 1;
  340. end;
  341. ispowerof2:=false;
  342. end;
  343. function pchar2pstring(p : pchar) : pstring;
  344. var
  345. w,i : longint;
  346. begin
  347. w:=strlen(p);
  348. for i:=w-1 downto 0 do
  349. p[i+1]:=p[i];
  350. p[0]:=chr(w);
  351. pchar2pstring:=pstring(p);
  352. end;
  353. function pstring2pchar(p : pstring) : pchar;
  354. var
  355. w,i : longint;
  356. begin
  357. w:=length(p^);
  358. for i:=1 to w do
  359. p^[i-1]:=p^[i];
  360. p^[w]:=#0;
  361. pstring2pchar:=pchar(p);
  362. end;
  363. function lowercase(c : char) : char;
  364. begin
  365. case c of
  366. #65..#90 : c := chr(ord (c) + 32);
  367. #154 : c:=#129; { german }
  368. #142 : c:=#132; { german }
  369. #153 : c:=#148; { german }
  370. #144 : c:=#130; { french }
  371. #128 : c:=#135; { french }
  372. #143 : c:=#134; { swedish/norge (?) }
  373. #165 : c:=#164; { spanish }
  374. #228 : c:=#229; { greek }
  375. #226 : c:=#231; { greek }
  376. #232 : c:=#227; { greek }
  377. end;
  378. lowercase := c;
  379. end;
  380. function strpnew(const s : string) : pchar;
  381. var
  382. p : pchar;
  383. begin
  384. getmem(p,length(s)+1);
  385. strpcopy(p,s);
  386. strpnew:=p;
  387. end;
  388. procedure strdispose(var p : pchar);
  389. begin
  390. if assigned(p) then
  391. begin
  392. freemem(p,strlen(p)+1);
  393. p:=nil;
  394. end;
  395. end;
  396. procedure stringdispose(var p : pstring);
  397. begin
  398. if assigned(p) then
  399. freemem(p,length(p^)+1);
  400. p:=nil;
  401. end;
  402. function stringdup(const s : string) : pstring;
  403. var
  404. p : pstring;
  405. begin
  406. getmem(p,length(s)+1);
  407. p^:=s;
  408. stringdup:=p;
  409. end;
  410. {*****************************************************************************
  411. GetSpeedValue
  412. *****************************************************************************}
  413. var
  414. Crc32Tbl : array[0..255] of longint;
  415. procedure MakeCRC32Tbl;
  416. var
  417. crc : longint;
  418. i,n : byte;
  419. begin
  420. for i:=0 to 255 do
  421. begin
  422. crc:=i;
  423. for n:=1 to 8 do
  424. if odd(crc) then
  425. crc:=(crc shr 1) xor longint($edb88320)
  426. else
  427. crc:=crc shr 1;
  428. Crc32Tbl[i]:=crc;
  429. end;
  430. end;
  431. {$ifopt R+}
  432. {$define Range_check_on}
  433. {$endif opt R+}
  434. {$R- needed here }
  435. {CRC 32}
  436. Function GetSpeedValue(Const s:String):longint;
  437. var
  438. i,InitCrc : longint;
  439. begin
  440. if Crc32Tbl[1]=0 then
  441. MakeCrc32Tbl;
  442. InitCrc:=$ffffffff;
  443. for i:=1 to Length(s) do
  444. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  445. GetSpeedValue:=InitCrc;
  446. end;
  447. {$ifdef Range_check_on}
  448. {$R+}
  449. {$undef Range_check_on}
  450. {$endif Range_check_on}
  451. {*****************************************************************************
  452. Ansistring (PChar+Length)
  453. *****************************************************************************}
  454. procedure ansistringdispose(var p : pchar;length : longint);
  455. begin
  456. if assigned(p) then
  457. freemem(p,length+1);
  458. p:=nil;
  459. end;
  460. { enable ansistring comparison }
  461. { 0 means equal }
  462. { 1 means p1 > p2 }
  463. { -1 means p1 < p2 }
  464. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  465. var
  466. i,j : longint;
  467. begin
  468. compareansistrings:=0;
  469. j:=min(length1,length2);
  470. i:=0;
  471. while (i<j) do
  472. begin
  473. if p1[i]>p2[i] then
  474. begin
  475. compareansistrings:=1;
  476. exit;
  477. end
  478. else
  479. if p1[i]<p2[i] then
  480. begin
  481. compareansistrings:=-1;
  482. exit;
  483. end;
  484. inc(i);
  485. end;
  486. if length1>length2 then
  487. compareansistrings:=1
  488. else
  489. if length1<length2 then
  490. compareansistrings:=-1;
  491. end;
  492. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  493. var
  494. p : pchar;
  495. begin
  496. getmem(p,length1+length2+1);
  497. move(p1[0],p[0],length1);
  498. move(p2[0],p[length1],length2+1);
  499. concatansistrings:=p;
  500. end;
  501. end.
  502. {
  503. $Log$
  504. Revision 1.1 2000-08-27 16:11:50 peter
  505. * moved some util functions from globals,cobjects to cutils
  506. * splitted files into finput,fmodule
  507. }