sstrings.inc 13 KB

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