sstrings.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 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: ValSInt;
  300. base : byte;
  301. negative : boolean;
  302. temp, prev: ValUInt;
  303. begin
  304. ValSignedInt := 0;
  305. Temp:=0;
  306. Code:=InitVal(s,negative,base);
  307. if Code>length(s) then
  308. exit;
  309. if negative and (s='-2147483648') then
  310. begin
  311. Code:=0;
  312. ValSignedInt:=$80000000;
  313. exit;
  314. end;
  315. while Code<=Length(s) do
  316. begin
  317. case s[Code] of
  318. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  319. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  320. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  321. else
  322. u:=16;
  323. end;
  324. Prev := Temp;
  325. Temp := Temp*ValUInt(base);
  326. If ((base = 10) and
  327. (prev > MaxSIntValue div ValUInt(Base))) or
  328. (Temp < prev) Then
  329. Begin
  330. ValSignedInt := 0;
  331. Exit
  332. End;
  333. if (u>=base) or
  334. ((base = 10) and
  335. (MaxSIntValue-Temp < u)) or
  336. ((base <> 10) and
  337. (MaxUIntValue-Temp < u)) then
  338. begin
  339. ValSignedInt:=0;
  340. exit;
  341. end;
  342. Temp:=Temp+u;
  343. inc(code);
  344. end;
  345. code := 0;
  346. ValSignedInt := ValSInt(Temp);
  347. If Negative Then
  348. ValSignedInt := -ValSignedInt;
  349. If Not(Negative) and (base <> 10) Then
  350. {sign extend the result to allow proper range checking}
  351. Case DestSize of
  352. 1: If (ValSignedInt > High(ShortInt)) and (ValSignedInt <= High(Byte)) Then
  353. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Byte));
  354. 2: If (ValSignedInt > High(Integer)) and (ValSignedInt <= High(Word)) Then
  355. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Word));
  356. { Uncomment the folling once full 64bit support is in place
  357. 4: If (ValSignedInt > High(Longint)) and (ValSignedInt <= High(Cardinal)) Then
  358. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Cardinal));}
  359. End;
  360. end;
  361. Function ValUnsignedInt(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR'];
  362. var
  363. u: ValUInt;
  364. base : byte;
  365. negative : boolean;
  366. prev: ValUInt;
  367. begin
  368. ValUnSignedInt:=0;
  369. Code:=InitVal(s,negative,base);
  370. If Negative or (Code>length(s)) Then
  371. Exit;
  372. while Code<=Length(s) do
  373. begin
  374. case s[Code] of
  375. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  376. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  377. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  378. else
  379. u:=16;
  380. end;
  381. prev := ValUnsignedInt;
  382. ValUnsignedInt:=ValUnsignedInt*ValUInt(base);
  383. If prev > ValUnsignedInt Then
  384. {we've had an overflow. Can't check this with
  385. "If ValUnsignedInt <= (MaxUIntValue div ValUInt(Base)) Then"
  386. because this division always overflows! (JM)}
  387. Begin
  388. ValUnsignedInt := 0;
  389. Exit
  390. End;
  391. if (u>=base) or (MaxUIntValue-ValUnsignedInt < u) then
  392. begin
  393. ValUnsignedInt:=0;
  394. exit;
  395. end;
  396. ValUnsignedInt:=ValUnsignedInt+u;
  397. inc(code);
  398. end;
  399. code := 0;
  400. end;
  401. Function ValFloat(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR'];
  402. var
  403. hd,
  404. esign,sign : valreal;
  405. exponent,i : longint;
  406. flags : byte;
  407. begin
  408. ValFloat:=0.0;
  409. code:=1;
  410. exponent:=0;
  411. esign:=1;
  412. flags:=0;
  413. sign:=1;
  414. while (code<=length(s)) and (s[code] in [' ',#9]) do
  415. inc(code);
  416. case s[code] of
  417. '+' : inc(code);
  418. '-' : begin
  419. sign:=-1;
  420. inc(code);
  421. end;
  422. end;
  423. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  424. begin
  425. { Read integer part }
  426. flags:=flags or 1;
  427. valfloat:=valfloat*10;
  428. valfloat:=valfloat+(ord(s[code])-ord('0'));
  429. inc(code);
  430. end;
  431. { Decimal ? }
  432. if (s[code]='.') and (length(s)>=code) then
  433. begin
  434. hd:=0.1;
  435. inc(code);
  436. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  437. begin
  438. { Read fractional part. }
  439. flags:=flags or 2;
  440. valfloat:=valfloat+hd*(ord(s[code])-ord('0'));
  441. hd:=hd/10.0;
  442. inc(code);
  443. end;
  444. end;
  445. { Again, read integer and fractional part}
  446. if flags=0 then
  447. begin
  448. valfloat:=0.0;
  449. exit;
  450. end;
  451. { Exponent ? }
  452. if (upcase(s[code])='E') and (length(s)>=code) then
  453. begin
  454. inc(code);
  455. if s[code]='+' then
  456. inc(code)
  457. else
  458. if s[code]='-' then
  459. begin
  460. esign:=-1;
  461. inc(code);
  462. end;
  463. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  464. begin
  465. valfloat:=0.0;
  466. exit;
  467. end;
  468. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  469. begin
  470. exponent:=exponent*10;
  471. exponent:=exponent+ord(s[code])-ord('0');
  472. inc(code);
  473. end;
  474. end;
  475. { Calculate Exponent }
  476. if esign>0 then
  477. for i:=1 to exponent do
  478. valfloat:=valfloat*10
  479. else
  480. for i:=1 to exponent do
  481. valfloat:=valfloat/10;
  482. { Not all characters are read ? }
  483. if length(s)>=code then
  484. begin
  485. valfloat:=0.0;
  486. exit;
  487. end;
  488. { evaluate sign }
  489. valfloat:=valfloat*sign;
  490. { success ! }
  491. code:=0;
  492. end;
  493. {$ifdef SUPPORT_FIXED}
  494. Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
  495. begin
  496. ValFixed := Fixed(ValFloat(s,code));
  497. end;
  498. {$endif SUPPORT_FIXED}
  499. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  500. begin
  501. Move (Buf[0],S[1],Len);
  502. S[0]:=chr(len);
  503. end;
  504. {
  505. $Log$
  506. Revision 1.30 1999-11-06 14:35:39 peter
  507. * truncated log
  508. Revision 1.29 1999/07/05 20:04:26 peter
  509. * removed temp defines
  510. Revision 1.28 1999/05/06 09:05:13 peter
  511. * generic write_float str_float
  512. Revision 1.27 1999/04/08 15:57:54 peter
  513. + subrange checking for readln()
  514. Revision 1.26 1999/04/05 12:28:27 michael
  515. + Fixed insert with char. length byte wrapped around in some cases.
  516. Revision 1.25 1999/04/01 22:11:50 peter
  517. * fixed '1.' parsing of val
  518. Revision 1.24 1999/04/01 22:00:49 peter
  519. * universal names for str/val (ansistr instead of stransi)
  520. * '1.' support for val() this is compatible with tp7
  521. Revision 1.23 1999/03/26 00:24:16 peter
  522. * last para changed to long for easier pushing with 4 byte aligns
  523. Revision 1.22 1999/03/16 17:49:36 jonas
  524. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  525. * in text.inc: changed RTE 106 when read integer values are out of bounds to RTE 201
  526. * in systemh.inc: disabled "support_fixed" for the i386 because it gave internal errors,
  527. Revision 1.21 1999/03/10 21:49:03 florian
  528. * str and val for extended use now int constants to minimize
  529. rounding error
  530. Revision 1.20 1999/03/03 15:23:57 michael
  531. + Added setstring for Delphi compatibility
  532. Revision 1.19 1999/01/25 20:24:28 peter
  533. * fixed insert to support again the max string length
  534. Revision 1.18 1999/01/11 19:26:55 jonas
  535. * made inster(string,string,index) a bit faster
  536. + overloaded insert(char,string,index)
  537. Revision 1.17 1998/12/15 22:43:02 peter
  538. * removed temp symbols
  539. Revision 1.16 1998/11/05 10:29:34 pierre
  540. * fix for length(char) in const expressions
  541. Revision 1.15 1998/11/04 10:20:50 peter
  542. * ansistring fixes
  543. Revision 1.14 1998/10/11 14:30:19 peter
  544. * small typo :(
  545. Revision 1.13 1998/10/10 15:28:46 peter
  546. + read single,fixed
  547. + val with code:longint
  548. + val for fixed
  549. Revision 1.12 1998/09/14 10:48:19 peter
  550. * FPC_ names
  551. * Heap manager is now system independent
  552. Revision 1.11 1998/08/11 21:39:07 peter
  553. * splitted default_extended from support_extended
  554. Revision 1.10 1998/08/08 12:28:13 florian
  555. * a lot small fixes to the extended data type work
  556. }