sstrings.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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+(ord(s[code])-ord('0'));
  426. inc(code);
  427. end;
  428. { Decimal ? }
  429. if (s[code]='.') and (length(s)>=code) then
  430. begin
  431. hd:=1.0;
  432. inc(code);
  433. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  434. begin
  435. { Read fractional part. }
  436. flags:=flags or 2;
  437. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  438. hd:=hd*10.0;
  439. inc(code);
  440. end;
  441. valfloat:=valfloat/hd;
  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. {
  475. if esign>0 then
  476. for i:=1 to exponent do
  477. valfloat:=valfloat*10
  478. else
  479. for i:=1 to exponent do
  480. valfloat:=valfloat/10; }
  481. hd:=1.0;
  482. for i:=1 to exponent do
  483. hd:=hd*10.0;
  484. if esign>0 then
  485. valfloat:=valfloat*hd
  486. else
  487. valfloat:=valfloat/hd;
  488. { Not all characters are read ? }
  489. if length(s)>=code then
  490. begin
  491. valfloat:=0.0;
  492. exit;
  493. end;
  494. { evaluate sign }
  495. valfloat:=valfloat*sign;
  496. { success ! }
  497. code:=0;
  498. end;
  499. {$ifdef SUPPORT_FIXED}
  500. Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
  501. begin
  502. ValFixed := Fixed(ValFloat(s,code));
  503. end;
  504. {$endif SUPPORT_FIXED}
  505. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  506. begin
  507. Move (Buf[0],S[1],Len);
  508. S[0]:=chr(len);
  509. end;
  510. {
  511. $Log$
  512. Revision 1.35 2000-04-06 11:51:47 pierre
  513. * fix for extended constants
  514. Revision 1.34 2000/02/09 16:59:31 peter
  515. * truncated log
  516. Revision 1.33 2000/01/07 16:41:36 daniel
  517. * copyright 2000
  518. Revision 1.32 2000/01/07 16:32:25 daniel
  519. * copyright 2000 added
  520. Revision 1.31 1999/12/11 19:07:44 jonas
  521. * avoid unwanted type conversion from cardinal to longint in val for
  522. signed and unsigned 32bit int
  523. Revision 1.30 1999/11/06 14:35:39 peter
  524. * truncated log
  525. }