sstrings.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  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.33 2000-01-07 16:41:36 daniel
  505. * copyright 2000
  506. Revision 1.32 2000/01/07 16:32:25 daniel
  507. * copyright 2000 added
  508. Revision 1.31 1999/12/11 19:07:44 jonas
  509. * avoid unwanted type conversion from cardinal to longint in val for
  510. signed and unsigned 32bit int
  511. Revision 1.30 1999/11/06 14:35:39 peter
  512. * truncated log
  513. Revision 1.29 1999/07/05 20:04:26 peter
  514. * removed temp defines
  515. Revision 1.28 1999/05/06 09:05:13 peter
  516. * generic write_float str_float
  517. Revision 1.27 1999/04/08 15:57:54 peter
  518. + subrange checking for readln()
  519. Revision 1.26 1999/04/05 12:28:27 michael
  520. + Fixed insert with char. length byte wrapped around in some cases.
  521. Revision 1.25 1999/04/01 22:11:50 peter
  522. * fixed '1.' parsing of val
  523. Revision 1.24 1999/04/01 22:00:49 peter
  524. * universal names for str/val (ansistr instead of stransi)
  525. * '1.' support for val() this is compatible with tp7
  526. Revision 1.23 1999/03/26 00:24:16 peter
  527. * last para changed to long for easier pushing with 4 byte aligns
  528. Revision 1.22 1999/03/16 17:49:36 jonas
  529. * changes for internal Val code (do a "make cycle OPT=-dvalintern" to test)
  530. * in text.inc: changed RTE 106 when read integer values are out of bounds to RTE 201
  531. * in systemh.inc: disabled "support_fixed" for the i386 because it gave internal errors,
  532. Revision 1.21 1999/03/10 21:49:03 florian
  533. * str and val for extended use now int constants to minimize
  534. rounding error
  535. Revision 1.20 1999/03/03 15:23:57 michael
  536. + Added setstring for Delphi compatibility
  537. Revision 1.19 1999/01/25 20:24:28 peter
  538. * fixed insert to support again the max string length
  539. Revision 1.18 1999/01/11 19:26:55 jonas
  540. * made inster(string,string,index) a bit faster
  541. + overloaded insert(char,string,index)
  542. Revision 1.17 1998/12/15 22:43:02 peter
  543. * removed temp symbols
  544. Revision 1.16 1998/11/05 10:29:34 pierre
  545. * fix for length(char) in const expressions
  546. Revision 1.15 1998/11/04 10:20:50 peter
  547. * ansistring fixes
  548. Revision 1.14 1998/10/11 14:30:19 peter
  549. * small typo :(
  550. Revision 1.13 1998/10/10 15:28:46 peter
  551. + read single,fixed
  552. + val with code:longint
  553. + val for fixed
  554. Revision 1.12 1998/09/14 10:48:19 peter
  555. * FPC_ names
  556. * Heap manager is now system independent
  557. Revision 1.11 1998/08/11 21:39:07 peter
  558. * splitted default_extended from support_extended
  559. Revision 1.10 1998/08/08 12:28:13 florian
  560. * a lot small fixes to the extended data type work
  561. }