sstrings.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  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 index+count>length(s) 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+Index>length(s) 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. if negative and (s='-2147483648') then
  313. begin
  314. Code:=0;
  315. ValSignedInt:=$80000000;
  316. exit;
  317. end;
  318. while Code<=Length(s) do
  319. begin
  320. case s[Code] of
  321. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  322. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  323. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  324. else
  325. u:=16;
  326. end;
  327. Prev := Temp;
  328. Temp := Temp*ValUInt(base);
  329. If (u >= base) or
  330. ((base = 10) and
  331. (MaxSIntValue-temp < u)) or
  332. ((base <> 10) and
  333. (ValUInt(MaxUIntValue-Temp) < u)) or
  334. (prev > ValUInt(MaxUIntValue) div ValUInt(Base)) Then
  335. Begin
  336. ValSignedInt := 0;
  337. Exit
  338. End;
  339. Temp:=Temp+u;
  340. inc(code);
  341. end;
  342. code := 0;
  343. ValSignedInt := ValSInt(Temp);
  344. If Negative Then
  345. ValSignedInt := -ValSignedInt;
  346. If Not(Negative) and (base <> 10) Then
  347. {sign extend the result to allow proper range checking}
  348. Case DestSize of
  349. 1: If (ValSignedInt > High(ShortInt)) and (ValSignedInt <= High(Byte)) Then
  350. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Byte));
  351. 2: If (ValSignedInt > High(Integer)) and (ValSignedInt <= High(Word)) Then
  352. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Word));
  353. { Uncomment the folling once full 64bit support is in place
  354. 4: If (ValSignedInt > High(Longint)) and (ValSignedInt <= High(Cardinal)) Then
  355. ValSignedInt := ValSignedInt or (MaxUIntValue xor High(Cardinal));}
  356. End;
  357. end;
  358. Function ValUnsignedInt(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR'];
  359. var
  360. u, prev: ValUInt;
  361. base : byte;
  362. negative : boolean;
  363. begin
  364. ValUnSignedInt:=0;
  365. Code:=InitVal(s,negative,base);
  366. If Negative or (Code>length(s)) Then
  367. Exit;
  368. while Code<=Length(s) do
  369. begin
  370. case s[Code] of
  371. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  372. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  373. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  374. else
  375. u:=16;
  376. end;
  377. prev := ValUnsignedInt;
  378. If (u>=base) or
  379. (ValUInt(MaxUIntValue-ValUnsignedInt) < u) or
  380. (prev > (ValUInt(MaxUIntValue) div ValUInt(Base))) then
  381. begin
  382. ValUnsignedInt:=0;
  383. exit;
  384. end;
  385. ValUnsignedInt:=ValUnsignedInt*ValUInt(base) + u;
  386. inc(code);
  387. end;
  388. code := 0;
  389. end;
  390. Function ValFloat(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR'];
  391. var
  392. hd,
  393. esign,sign : valreal;
  394. exponent,i : longint;
  395. flags : byte;
  396. begin
  397. ValFloat:=0.0;
  398. code:=1;
  399. exponent:=0;
  400. esign:=1;
  401. flags:=0;
  402. sign:=1;
  403. while (code<=length(s)) and (s[code] in [' ',#9]) do
  404. inc(code);
  405. case s[code] of
  406. '+' : inc(code);
  407. '-' : begin
  408. sign:=-1;
  409. inc(code);
  410. end;
  411. end;
  412. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  413. begin
  414. { Read integer part }
  415. flags:=flags or 1;
  416. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  417. inc(code);
  418. end;
  419. { Decimal ? }
  420. if (s[code]='.') and (length(s)>=code) then
  421. begin
  422. hd:=1.0;
  423. inc(code);
  424. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  425. begin
  426. { Read fractional part. }
  427. flags:=flags or 2;
  428. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  429. hd:=hd*10.0;
  430. inc(code);
  431. end;
  432. valfloat:=valfloat/hd;
  433. end;
  434. { Again, read integer and fractional part}
  435. if flags=0 then
  436. begin
  437. valfloat:=0.0;
  438. exit;
  439. end;
  440. { Exponent ? }
  441. if (upcase(s[code])='E') and (length(s)>=code) then
  442. begin
  443. inc(code);
  444. if s[code]='+' then
  445. inc(code)
  446. else
  447. if s[code]='-' then
  448. begin
  449. esign:=-1;
  450. inc(code);
  451. end;
  452. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  453. begin
  454. valfloat:=0.0;
  455. exit;
  456. end;
  457. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  458. begin
  459. exponent:=exponent*10;
  460. exponent:=exponent+ord(s[code])-ord('0');
  461. inc(code);
  462. end;
  463. end;
  464. { Calculate Exponent }
  465. {
  466. if esign>0 then
  467. for i:=1 to exponent do
  468. valfloat:=valfloat*10
  469. else
  470. for i:=1 to exponent do
  471. valfloat:=valfloat/10; }
  472. hd:=1.0;
  473. for i:=1 to exponent do
  474. hd:=hd*10.0;
  475. if esign>0 then
  476. valfloat:=valfloat*hd
  477. else
  478. valfloat:=valfloat/hd;
  479. { Not all characters are read ? }
  480. if length(s)>=code then
  481. begin
  482. valfloat:=0.0;
  483. exit;
  484. end;
  485. { evaluate sign }
  486. valfloat:=valfloat*sign;
  487. { success ! }
  488. code:=0;
  489. end;
  490. {$ifdef SUPPORT_FIXED}
  491. Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
  492. begin
  493. ValFixed := Fixed(ValFloat(s,code));
  494. end;
  495. {$endif SUPPORT_FIXED}
  496. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  497. begin
  498. Move (Buf[0],S[1],Len);
  499. S[0]:=chr(len);
  500. end;
  501. {
  502. $Log$
  503. Revision 1.5 2000-11-06 20:34:24 peter
  504. * changed ver1_0 defines to temporary defs
  505. Revision 1.4 2000/10/21 18:20:17 florian
  506. * a lot of small changes:
  507. - setlength is internal
  508. - win32 graph unit extended
  509. ....
  510. Revision 1.3 2000/07/28 12:29:49 jonas
  511. * fixed web bug1069
  512. * fixed similar (and other) problems in val() for int64 and qword
  513. (both merged from fixes branch)
  514. Revision 1.2 2000/07/13 11:33:45 michael
  515. + removed logs
  516. }