sstrings.inc 12 KB

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