cutils.pas 14 KB

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