sstrings.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  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-u) div ValUInt(Base)<prev) then
  374. begin
  375. ValUnsignedInt:=0;
  376. exit;
  377. end;
  378. ValUnsignedInt:=ValUnsignedInt*ValUInt(base) + u;
  379. inc(code);
  380. end;
  381. code := 0;
  382. end;
  383. Function ValFloat(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR'];
  384. var
  385. hd,
  386. esign,sign : valreal;
  387. exponent,i : longint;
  388. flags : byte;
  389. begin
  390. ValFloat:=0.0;
  391. code:=1;
  392. exponent:=0;
  393. esign:=1;
  394. flags:=0;
  395. sign:=1;
  396. while (code<=length(s)) and (s[code] in [' ',#9]) do
  397. inc(code);
  398. case s[code] of
  399. '+' : inc(code);
  400. '-' : begin
  401. sign:=-1;
  402. inc(code);
  403. end;
  404. end;
  405. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  406. begin
  407. { Read integer part }
  408. flags:=flags or 1;
  409. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  410. inc(code);
  411. end;
  412. { Decimal ? }
  413. if (s[code]='.') and (length(s)>=code) then
  414. begin
  415. hd:=1.0;
  416. inc(code);
  417. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  418. begin
  419. { Read fractional part. }
  420. flags:=flags or 2;
  421. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  422. hd:=hd*10.0;
  423. inc(code);
  424. end;
  425. valfloat:=valfloat/hd;
  426. end;
  427. { Again, read integer and fractional part}
  428. if flags=0 then
  429. begin
  430. valfloat:=0.0;
  431. exit;
  432. end;
  433. { Exponent ? }
  434. if (upcase(s[code])='E') and (length(s)>=code) then
  435. begin
  436. inc(code);
  437. if s[code]='+' then
  438. inc(code)
  439. else
  440. if s[code]='-' then
  441. begin
  442. esign:=-1;
  443. inc(code);
  444. end;
  445. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  446. begin
  447. valfloat:=0.0;
  448. exit;
  449. end;
  450. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  451. begin
  452. exponent:=exponent*10;
  453. exponent:=exponent+ord(s[code])-ord('0');
  454. inc(code);
  455. end;
  456. end;
  457. { Calculate Exponent }
  458. {
  459. if esign>0 then
  460. for i:=1 to exponent do
  461. valfloat:=valfloat*10
  462. else
  463. for i:=1 to exponent do
  464. valfloat:=valfloat/10; }
  465. hd:=1.0;
  466. for i:=1 to exponent do
  467. hd:=hd*10.0;
  468. if esign>0 then
  469. valfloat:=valfloat*hd
  470. else
  471. valfloat:=valfloat/hd;
  472. { Not all characters are read ? }
  473. if length(s)>=code then
  474. begin
  475. valfloat:=0.0;
  476. exit;
  477. end;
  478. { evaluate sign }
  479. valfloat:=valfloat*sign;
  480. { success ! }
  481. code:=0;
  482. end;
  483. {$ifdef SUPPORT_FIXED}
  484. Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
  485. begin
  486. ValFixed := Fixed(ValFloat(s,code));
  487. end;
  488. {$endif SUPPORT_FIXED}
  489. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  490. begin
  491. Move (Buf[0],S[1],Len);
  492. S[0]:=chr(len);
  493. end;
  494. {
  495. $Log$
  496. Revision 1.8 2000-12-09 20:52:41 florian
  497. * val for dword and qword didn't handle the max values
  498. correctly
  499. * val for qword works again
  500. + val with int64/qword and ansistring implemented
  501. Revision 1.7 2000/11/23 11:41:56 jonas
  502. * fix for web bug 1265 by Peter (merged)
  503. Revision 1.6 2000/11/17 17:01:23 jonas
  504. * fixed bug for val when processing -2147483648 and low(int64) (merged)
  505. Revision 1.5 2000/11/06 20:34:24 peter
  506. * changed ver1_0 defines to temporary defs
  507. Revision 1.4 2000/10/21 18:20:17 florian
  508. * a lot of small changes:
  509. - setlength is internal
  510. - win32 graph unit extended
  511. ....
  512. Revision 1.3 2000/07/28 12:29:49 jonas
  513. * fixed web bug1069
  514. * fixed similar (and other) problems in val() for int64 and qword
  515. (both merged from fixes branch)
  516. Revision 1.2 2000/07/13 11:33:45 michael
  517. + removed logs
  518. }