sstrings.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. subroutines for string handling
  13. ****************************************************************************}
  14. {$I real2str.inc}
  15. function copy(const s : shortstring;index : StrLenInt;count : StrLenInt): shortstring;
  16. begin
  17. if count<0 then
  18. count:=0;
  19. if index>1 then
  20. dec(index)
  21. else
  22. index:=0;
  23. if index>length(s) then
  24. count:=0
  25. else
  26. if index+count>length(s) then
  27. count:=length(s)-index;
  28. Copy[0]:=chr(Count);
  29. Move(s[Index+1],Copy[1],Count);
  30. end;
  31. procedure delete(var s : shortstring;index : StrLenInt;count : StrLenInt);
  32. begin
  33. if index<=0 then
  34. begin
  35. inc(count,index-1);
  36. index:=1;
  37. end;
  38. if (Index<=Length(s)) and (Count>0) then
  39. begin
  40. if Count+Index>length(s) then
  41. Count:=length(s)-Index+1;
  42. s[0]:=Chr(length(s)-Count);
  43. if Index<=Length(s) then
  44. Move(s[Index+Count],s[Index],Length(s)-Index+1);
  45. end;
  46. end;
  47. procedure insert(const source : shortstring;var s : shortstring;index : StrLenInt);
  48. var
  49. cut,srclen,indexlen : longint;
  50. begin
  51. if index<1 then
  52. index:=1;
  53. if index>length(s) then
  54. index:=length(s)+1;
  55. indexlen:=Length(s)-Index+1;
  56. srclen:=length(Source);
  57. if length(source)+length(s)>=sizeof(s) then
  58. begin
  59. cut:=length(source)+length(s)-sizeof(s)+1;
  60. if cut>indexlen then
  61. begin
  62. dec(srclen,cut-indexlen);
  63. indexlen:=0;
  64. end
  65. else
  66. dec(indexlen,cut);
  67. end;
  68. move(s[Index],s[Index+srclen],indexlen);
  69. move(Source[1],s[Index],srclen);
  70. s[0]:=chr(index+srclen+indexlen-1);
  71. end;
  72. procedure insert(source : Char;var s : shortstring;index : StrLenInt);
  73. var
  74. indexlen : longint;
  75. begin
  76. if index<1 then
  77. index:=1;
  78. if index>length(s) then
  79. index:=length(s)+1;
  80. indexlen:=Length(s)-Index+1;
  81. if (length(s)+1=sizeof(s)) and (indexlen>0) then
  82. dec(indexlen);
  83. move(s[Index],s[Index+1],indexlen);
  84. s[Index]:=Source;
  85. s[0]:=chr(index+indexlen);
  86. end;
  87. function pos(const substr : shortstring;const s : shortstring):StrLenInt;
  88. var
  89. i,j : StrLenInt;
  90. e : boolean;
  91. begin
  92. i := 0;
  93. j := 0;
  94. e:=(length(SubStr)>0);
  95. while e and (i<=Length(s)-Length(SubStr)) do
  96. begin
  97. inc(i);
  98. if (SubStr[1]=s[i]) and (Substr=Copy(s,i,Length(SubStr))) then
  99. begin
  100. j:=i;
  101. e:=false;
  102. end;
  103. end;
  104. Pos:=j;
  105. end;
  106. {Faster when looking for a single char...}
  107. function pos(c:char;const s:shortstring):StrLenInt;
  108. var
  109. i : StrLenInt;
  110. begin
  111. for i:=1 to length(s) do
  112. if s[i]=c then
  113. begin
  114. pos:=i;
  115. exit;
  116. end;
  117. pos:=0;
  118. end;
  119. procedure SetLength(var s:shortstring;len:StrLenInt);
  120. begin
  121. if Len>255 then
  122. Len:=255;
  123. s[0]:=chr(len);
  124. end;
  125. function copy(c:char;index : StrLenInt;count : StrLenInt): shortstring;
  126. begin
  127. if (index=1) and (Count>0) then
  128. Copy:=c
  129. else
  130. Copy:='';
  131. end;
  132. function pos(const substr : shortstring;c:char): StrLenInt;
  133. begin
  134. if (length(substr)=1) and (substr[1]=c) then
  135. Pos:=1
  136. else
  137. Pos:=0;
  138. end;
  139. { removed must be internal to be accepted in const expr !! PM
  140. function length(c:char):StrLenInt;
  141. begin
  142. Length:=1;
  143. end;
  144. }
  145. {$ifdef IBM_CHAR_SET}
  146. const
  147. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  148. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  149. {$endif}
  150. function upcase(c : char) : char;
  151. {$IFDEF IBM_CHAR_SET}
  152. var
  153. i : longint;
  154. {$ENDIF}
  155. begin
  156. if (c in ['a'..'z']) then
  157. upcase:=char(byte(c)-32)
  158. else
  159. {$IFDEF IBM_CHAR_SET}
  160. begin
  161. i:=Pos(c,LoCaseTbl);
  162. if i>0 then
  163. upcase:=UpCaseTbl[i]
  164. else
  165. upcase:=c;
  166. end;
  167. {$ELSE}
  168. upcase:=c;
  169. {$ENDIF}
  170. end;
  171. function upcase(const s : shortstring) : shortstring;
  172. var
  173. i : longint;
  174. begin
  175. upcase[0]:=s[0];
  176. for i := 1 to length (s) do
  177. upcase[i] := upcase (s[i]);
  178. end;
  179. {$ifndef RTLLITE}
  180. function lowercase(c : char) : char;
  181. {$IFDEF IBM_CHAR_SET}
  182. var
  183. i : longint;
  184. {$ENDIF}
  185. begin
  186. if (c in ['A'..'Z']) then
  187. lowercase:=char(byte(c)+32)
  188. else
  189. {$IFDEF IBM_CHAR_SET}
  190. begin
  191. i:=Pos(c,UpCaseTbl);
  192. if i>0 then
  193. lowercase:=LoCaseTbl[i]
  194. else
  195. lowercase:=c;
  196. end;
  197. {$ELSE}
  198. lowercase:=c;
  199. {$ENDIF}
  200. end;
  201. function lowercase(const s : shortstring) : shortstring;
  202. var
  203. i : longint;
  204. begin
  205. lowercase [0]:=s[0];
  206. for i:=1 to length(s) do
  207. lowercase[i]:=lowercase (s[i]);
  208. end;
  209. function hexstr(val : longint;cnt : byte) : shortstring;
  210. const
  211. HexTbl : array[0..15] of char='0123456789ABCDEF';
  212. var
  213. i : longint;
  214. begin
  215. hexstr[0]:=char(cnt);
  216. for i:=cnt downto 1 do
  217. begin
  218. hexstr[i]:=hextbl[val and $f];
  219. val:=val shr 4;
  220. end;
  221. end;
  222. function binstr(val : longint;cnt : byte) : shortstring;
  223. var
  224. i : longint;
  225. begin
  226. binstr[0]:=char(cnt);
  227. for i:=cnt downto 1 do
  228. begin
  229. binstr[i]:=char(48+val and 1);
  230. val:=val shr 1;
  231. end;
  232. end;
  233. {$endif RTLLITE}
  234. function space (b : byte): shortstring;
  235. begin
  236. space[0] := chr(b);
  237. FillChar (Space[1],b,' ');
  238. end;
  239. {*****************************************************************************
  240. Str() Helpers
  241. *****************************************************************************}
  242. procedure ShortStr_Float(d : ValReal;len,fr,rt : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT'];
  243. begin
  244. str_real(len,fr,d,treal_type(rt),s);
  245. end;
  246. procedure int_str_longint(v : longint;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT'];
  247. begin
  248. int_str(v,s);
  249. if length(s)<len then
  250. s:=space(len-length(s))+s;
  251. end;
  252. procedure int_str_cardinal(v : cardinal;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_CARDINAL'];
  253. begin
  254. int_str(v,s);
  255. if length(s)<len then
  256. s:=space(len-length(s))+s;
  257. end;
  258. {*****************************************************************************
  259. Val() Functions
  260. *****************************************************************************}
  261. Function InitVal(const s:shortstring;var negativ:boolean;var base:byte):ValSInt;
  262. var
  263. Code : Longint;
  264. begin
  265. {Skip Spaces and Tab}
  266. code:=1;
  267. while (code<=length(s)) and (s[code] in [' ',#9]) do
  268. inc(code);
  269. {Sign}
  270. negativ:=false;
  271. case s[code] of
  272. '-' : begin
  273. negativ:=true;
  274. inc(code);
  275. end;
  276. '+' : inc(code);
  277. end;
  278. {Base}
  279. base:=10;
  280. if code<=length(s) then
  281. begin
  282. case s[code] of
  283. '$' : begin
  284. base:=16;
  285. repeat
  286. inc(code);
  287. until (code>=length(s)) or (s[code]<>'0');
  288. end;
  289. '%' : begin
  290. base:=2;
  291. inc(code);
  292. end;
  293. end;
  294. end;
  295. InitVal:=code;
  296. end;
  297. Function ValSignedInt(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR'];
  298. var
  299. u, temp, prev: ValUInt;
  300. base : byte;
  301. negative : boolean;
  302. begin
  303. ValSignedInt := 0;
  304. Temp:=0;
  305. Code:=InitVal(s,negative,base);
  306. if Code>length(s) then
  307. exit;
  308. if negative and (s='-2147483648') then
  309. begin
  310. Code:=0;
  311. ValSignedInt:=$80000000;
  312. exit;
  313. end;
  314. while Code<=Length(s) do
  315. begin
  316. case s[Code] of
  317. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  318. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  319. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  320. else
  321. u:=16;
  322. end;
  323. Prev := Temp;
  324. Temp := Temp*ValUInt(base);
  325. If ((base = 10) and
  326. (prev > MaxSIntValue div ValUInt(Base))) or
  327. (Temp < prev) Then
  328. Begin
  329. ValSignedInt := 0;
  330. Exit
  331. End;
  332. if (u>=base) or
  333. ((base = 10) and
  334. (MaxSIntValue < u+temp)) or
  335. ((base <> 10) and
  336. (ValUInt(MaxUIntValue-Temp) < u)) then
  337. begin
  338. ValSignedInt:=0;
  339. exit;
  340. end;
  341. Temp:=Temp+u;
  342. inc(code);
  343. end;
  344. code := 0;
  345. ValSignedInt := ValSInt(Temp);
  346. If Negative Then
  347. ValSignedInt := -ValSignedInt;
  348. If Not(Negative) and (base <> 10) Then
  349. {sign extend the result to allow proper range checking}
  350. Case DestSize of
  351. 1: If (ValSignedInt > High(ShortInt)) and (ValSignedInt <= High(Byte)) Then
  352. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Byte));
  353. 2: If (ValSignedInt > High(Integer)) and (ValSignedInt <= High(Word)) Then
  354. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Word));
  355. { Uncomment the folling once full 64bit support is in place
  356. 4: If (ValSignedInt > High(Longint)) and (ValSignedInt <= High(Cardinal)) Then
  357. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Cardinal));}
  358. End;
  359. end;
  360. Function ValUnsignedInt(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR'];
  361. var
  362. u, prev: ValUInt;
  363. base : byte;
  364. negative : boolean;
  365. begin
  366. ValUnSignedInt:=0;
  367. Code:=InitVal(s,negative,base);
  368. If Negative or (Code>length(s)) Then
  369. Exit;
  370. while Code<=Length(s) do
  371. begin
  372. case s[Code] of
  373. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  374. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  375. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  376. else
  377. u:=16;
  378. end;
  379. prev := ValUnsignedInt;
  380. ValUnsignedInt:=ValUnsignedInt*ValUInt(base);
  381. If prev > ValUnsignedInt Then
  382. {we've had an overflow. Can't check this with
  383. "If ValUnsignedInt <= (MaxUIntValue div ValUInt(Base)) Then"
  384. because this division always overflows! (JM)}
  385. Begin
  386. ValUnsignedInt := 0;
  387. Exit
  388. End;
  389. if (u>=base) or (ValUInt(MaxUIntValue-ValUnsignedInt) < u) then
  390. begin
  391. ValUnsignedInt:=0;
  392. exit;
  393. end;
  394. ValUnsignedInt:=ValUnsignedInt+u;
  395. inc(code);
  396. end;
  397. code := 0;
  398. end;
  399. Function ValFloat(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR'];
  400. var
  401. hd,
  402. esign,sign : valreal;
  403. exponent,i : longint;
  404. flags : byte;
  405. begin
  406. ValFloat:=0.0;
  407. code:=1;
  408. exponent:=0;
  409. esign:=1;
  410. flags:=0;
  411. sign:=1;
  412. while (code<=length(s)) and (s[code] in [' ',#9]) do
  413. inc(code);
  414. case s[code] of
  415. '+' : inc(code);
  416. '-' : begin
  417. sign:=-1;
  418. inc(code);
  419. end;
  420. end;
  421. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  422. begin
  423. { Read integer part }
  424. flags:=flags or 1;
  425. valfloat:=valfloat*10;
  426. valfloat:=valfloat+(ord(s[code])-ord('0'));
  427. inc(code);
  428. end;
  429. { Decimal ? }
  430. if (s[code]='.') and (length(s)>=code) then
  431. begin
  432. hd:=0.1;
  433. inc(code);
  434. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  435. begin
  436. { Read fractional part. }
  437. flags:=flags or 2;
  438. valfloat:=valfloat+hd*(ord(s[code])-ord('0'));
  439. hd:=hd/10.0;
  440. inc(code);
  441. end;
  442. end;
  443. { Again, read integer and fractional part}
  444. if flags=0 then
  445. begin
  446. valfloat:=0.0;
  447. exit;
  448. end;
  449. { Exponent ? }
  450. if (upcase(s[code])='E') and (length(s)>=code) then
  451. begin
  452. inc(code);
  453. if s[code]='+' then
  454. inc(code)
  455. else
  456. if s[code]='-' then
  457. begin
  458. esign:=-1;
  459. inc(code);
  460. end;
  461. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  462. begin
  463. valfloat:=0.0;
  464. exit;
  465. end;
  466. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  467. begin
  468. exponent:=exponent*10;
  469. exponent:=exponent+ord(s[code])-ord('0');
  470. inc(code);
  471. end;
  472. end;
  473. { Calculate Exponent }
  474. if esign>0 then
  475. for i:=1 to exponent do
  476. valfloat:=valfloat*10
  477. else
  478. for i:=1 to exponent do
  479. valfloat:=valfloat/10;
  480. { Not all characters are read ? }
  481. if length(s)>=code then
  482. begin
  483. valfloat:=0.0;
  484. exit;
  485. end;
  486. { evaluate sign }
  487. valfloat:=valfloat*sign;
  488. { success ! }
  489. code:=0;
  490. end;
  491. {$ifdef SUPPORT_FIXED}
  492. Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
  493. begin
  494. ValFixed := Fixed(ValFloat(s,code));
  495. end;
  496. {$endif SUPPORT_FIXED}
  497. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  498. begin
  499. Move (Buf[0],S[1],Len);
  500. S[0]:=chr(len);
  501. end;
  502. {
  503. $Log$
  504. Revision 1.34 2000-02-09 16:59:31 peter
  505. * truncated log
  506. Revision 1.33 2000/01/07 16:41:36 daniel
  507. * copyright 2000
  508. Revision 1.32 2000/01/07 16:32:25 daniel
  509. * copyright 2000 added
  510. Revision 1.31 1999/12/11 19:07:44 jonas
  511. * avoid unwanted type conversion from cardinal to longint in val for
  512. signed and unsigned 32bit int
  513. Revision 1.30 1999/11/06 14:35:39 peter
  514. * truncated log
  515. }