sstrings.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  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. function lowercase(c : char) : char;
  184. {$IFDEF IBM_CHAR_SET}
  185. var
  186. i : longint;
  187. {$ENDIF}
  188. begin
  189. if (c in ['A'..'Z']) then
  190. lowercase:=char(byte(c)+32)
  191. else
  192. {$IFDEF IBM_CHAR_SET}
  193. begin
  194. i:=Pos(c,UpCaseTbl);
  195. if i>0 then
  196. lowercase:=LoCaseTbl[i]
  197. else
  198. lowercase:=c;
  199. end;
  200. {$ELSE}
  201. lowercase:=c;
  202. {$ENDIF}
  203. end;
  204. function lowercase(const s : shortstring) : shortstring;
  205. var
  206. i : longint;
  207. begin
  208. lowercase [0]:=s[0];
  209. for i:=1 to length(s) do
  210. lowercase[i]:=lowercase (s[i]);
  211. end;
  212. const
  213. HexTbl : array[0..15] of char='0123456789ABCDEF';
  214. function hexstr(val : longint;cnt : byte) : shortstring;
  215. var
  216. i : longint;
  217. begin
  218. hexstr[0]:=char(cnt);
  219. for i:=cnt downto 1 do
  220. begin
  221. hexstr[i]:=hextbl[val and $f];
  222. val:=val shr 4;
  223. end;
  224. end;
  225. function binstr(val : longint;cnt : byte) : shortstring;
  226. var
  227. i : longint;
  228. begin
  229. binstr[0]:=char(cnt);
  230. for i:=cnt downto 1 do
  231. begin
  232. binstr[i]:=char(48+val and 1);
  233. val:=val shr 1;
  234. end;
  235. end;
  236. function hexstr(val : int64;cnt : byte) : shortstring;
  237. var
  238. i : longint;
  239. begin
  240. hexstr[0]:=char(cnt);
  241. for i:=cnt downto 1 do
  242. begin
  243. hexstr[i]:=hextbl[val and $f];
  244. val:=val shr 4;
  245. end;
  246. end;
  247. function binstr(val : int64;cnt : byte) : shortstring;
  248. var
  249. i : longint;
  250. begin
  251. binstr[0]:=char(cnt);
  252. for i:=cnt downto 1 do
  253. begin
  254. binstr[i]:=char(48+val and 1);
  255. val:=val shr 1;
  256. end;
  257. end;
  258. function space (b : byte): shortstring;
  259. begin
  260. space[0] := chr(b);
  261. FillChar (Space[1],b,' ');
  262. end;
  263. {*****************************************************************************
  264. Str() Helpers
  265. *****************************************************************************}
  266. procedure ShortStr_Float(d : ValReal;len,fr,rt : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT'];
  267. begin
  268. str_real(len,fr,d,treal_type(rt),s);
  269. end;
  270. procedure int_str_longint(v : longint;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT'];
  271. begin
  272. int_str(v,s);
  273. if length(s)<len then
  274. s:=space(len-length(s))+s;
  275. end;
  276. procedure int_str_cardinal(v : cardinal;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_CARDINAL'];
  277. begin
  278. int_str(v,s);
  279. if length(s)<len then
  280. s:=space(len-length(s))+s;
  281. end;
  282. {*****************************************************************************
  283. Val() Functions
  284. *****************************************************************************}
  285. Function InitVal(const s:shortstring;var negativ:boolean;var base:byte):ValSInt;
  286. var
  287. Code : Longint;
  288. begin
  289. {Skip Spaces and Tab}
  290. code:=1;
  291. while (code<=length(s)) and (s[code] in [' ',#9]) do
  292. inc(code);
  293. {Sign}
  294. negativ:=false;
  295. case s[code] of
  296. '-' : begin
  297. negativ:=true;
  298. inc(code);
  299. end;
  300. '+' : inc(code);
  301. end;
  302. {Base}
  303. base:=10;
  304. if code<=length(s) then
  305. begin
  306. case s[code] of
  307. '$' : begin
  308. base:=16;
  309. repeat
  310. inc(code);
  311. until (code>=length(s)) or (s[code]<>'0');
  312. end;
  313. '%' : begin
  314. base:=2;
  315. inc(code);
  316. end;
  317. end;
  318. end;
  319. InitVal:=code;
  320. end;
  321. Function ValSignedInt(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR'];
  322. var
  323. u, temp, prev, maxValue: ValUInt;
  324. base : byte;
  325. negative : boolean;
  326. begin
  327. ValSignedInt := 0;
  328. Temp:=0;
  329. Code:=InitVal(s,negative,base);
  330. if Code>length(s) then
  331. exit;
  332. maxValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  333. while Code<=Length(s) do
  334. begin
  335. case s[Code] of
  336. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  337. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  338. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  339. else
  340. u:=16;
  341. end;
  342. Prev := Temp;
  343. Temp := Temp*ValUInt(base);
  344. If (u >= base) or
  345. ((base = 10) and
  346. (MaxSIntValue-temp+ord(negative) < u)) or
  347. ((base <> 10) and
  348. (ValUInt(MaxUIntValue-Temp) < u)) or
  349. (prev > maxValue) Then
  350. Begin
  351. ValSignedInt := 0;
  352. Exit
  353. End;
  354. Temp:=Temp+u;
  355. inc(code);
  356. end;
  357. code := 0;
  358. ValSignedInt := ValSInt(Temp);
  359. If Negative Then
  360. ValSignedInt := -ValSignedInt;
  361. If Not(Negative) and (base <> 10) Then
  362. {sign extend the result to allow proper range checking}
  363. Case DestSize of
  364. 1: ValSignedInt := shortint(ValSignedInt);
  365. 2: ValSignedInt := smallint(ValSignedInt);
  366. { Uncomment the folling once full 64bit support is in place
  367. 4: ValSignedInt := longint(ValSignedInt);}
  368. End;
  369. end;
  370. Function ValUnsignedInt(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR'];
  371. var
  372. u, prev : ValUInt;
  373. base : byte;
  374. negative : boolean;
  375. begin
  376. ValUnSignedInt:=0;
  377. Code:=InitVal(s,negative,base);
  378. If Negative or (Code>length(s)) Then
  379. Exit;
  380. while Code<=Length(s) do
  381. begin
  382. case s[Code] of
  383. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  384. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  385. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  386. else
  387. u:=16;
  388. end;
  389. prev := ValUnsignedInt;
  390. If (u>=base) or
  391. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  392. begin
  393. ValUnsignedInt:=0;
  394. exit;
  395. end;
  396. ValUnsignedInt:=ValUnsignedInt*ValUInt(base) + u;
  397. inc(code);
  398. end;
  399. code := 0;
  400. end;
  401. Function ValFloat(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR'];
  402. var
  403. hd,
  404. esign,sign : valreal;
  405. exponent,i : longint;
  406. flags : byte;
  407. begin
  408. ValFloat:=0.0;
  409. code:=1;
  410. exponent:=0;
  411. esign:=1;
  412. flags:=0;
  413. sign:=1;
  414. while (code<=length(s)) and (s[code] in [' ',#9]) do
  415. inc(code);
  416. case s[code] of
  417. '+' : inc(code);
  418. '-' : begin
  419. sign:=-1;
  420. inc(code);
  421. end;
  422. end;
  423. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  424. begin
  425. { Read integer part }
  426. flags:=flags or 1;
  427. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  428. inc(code);
  429. end;
  430. { Decimal ? }
  431. if (s[code]='.') and (length(s)>=code) then
  432. begin
  433. hd:=1.0;
  434. inc(code);
  435. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  436. begin
  437. { Read fractional part. }
  438. flags:=flags or 2;
  439. valfloat:=valfloat*10+(ord(s[code])-ord('0'));
  440. hd:=hd*10.0;
  441. inc(code);
  442. end;
  443. valfloat:=valfloat/hd;
  444. end;
  445. { Again, read integer and fractional part}
  446. if flags=0 then
  447. begin
  448. valfloat:=0.0;
  449. exit;
  450. end;
  451. { Exponent ? }
  452. if (upcase(s[code])='E') and (length(s)>=code) then
  453. begin
  454. inc(code);
  455. if s[code]='+' then
  456. inc(code)
  457. else
  458. if s[code]='-' then
  459. begin
  460. esign:=-1;
  461. inc(code);
  462. end;
  463. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  464. begin
  465. valfloat:=0.0;
  466. exit;
  467. end;
  468. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  469. begin
  470. exponent:=exponent*10;
  471. exponent:=exponent+ord(s[code])-ord('0');
  472. inc(code);
  473. end;
  474. end;
  475. { Calculate Exponent }
  476. {
  477. if esign>0 then
  478. for i:=1 to exponent do
  479. valfloat:=valfloat*10
  480. else
  481. for i:=1 to exponent do
  482. valfloat:=valfloat/10; }
  483. hd:=1.0;
  484. for i:=1 to exponent do
  485. hd:=hd*10.0;
  486. if esign>0 then
  487. valfloat:=valfloat*hd
  488. else
  489. valfloat:=valfloat/hd;
  490. { Not all characters are read ? }
  491. if length(s)>=code then
  492. begin
  493. valfloat:=0.0;
  494. exit;
  495. end;
  496. { evaluate sign }
  497. valfloat:=valfloat*sign;
  498. { success ! }
  499. code:=0;
  500. end;
  501. {$ifdef SUPPORT_FIXED}
  502. Function ValFixed(const s : shortstring;var code : ValSInt): Fixed; [public, alias:'FPC_VAL_FIXED_SHORTSTR'];
  503. begin
  504. ValFixed := Fixed(ValFloat(s,code));
  505. end;
  506. {$endif SUPPORT_FIXED}
  507. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  508. begin
  509. Move (Buf[0],S[1],Len);
  510. S[0]:=chr(len);
  511. end;
  512. {
  513. $Log$
  514. Revision 1.12 2001-06-04 11:43:51 peter
  515. * Formal const to var fixes
  516. * Hexstr(int64) added
  517. Revision 1.11 2001/04/13 22:30:04 peter
  518. * remove warnings
  519. Revision 1.10 2001/04/13 18:06:28 peter
  520. * removed rtllite define
  521. Revision 1.9 2001/03/03 12:38:53 jonas
  522. * made val for longints a bit faster
  523. Revision 1.8 2000/12/09 20:52:41 florian
  524. * val for dword and qword didn't handle the max values
  525. correctly
  526. * val for qword works again
  527. + val with int64/qword and ansistring implemented
  528. Revision 1.7 2000/11/23 11:41:56 jonas
  529. * fix for web bug 1265 by Peter (merged)
  530. Revision 1.6 2000/11/17 17:01:23 jonas
  531. * fixed bug for val when processing -2147483648 and low(int64) (merged)
  532. Revision 1.5 2000/11/06 20:34:24 peter
  533. * changed ver1_0 defines to temporary defs
  534. Revision 1.4 2000/10/21 18:20:17 florian
  535. * a lot of small changes:
  536. - setlength is internal
  537. - win32 graph unit extended
  538. ....
  539. Revision 1.3 2000/07/28 12:29:49 jonas
  540. * fixed web bug1069
  541. * fixed similar (and other) problems in val() for int64 and qword
  542. (both merged from fixes branch)
  543. Revision 1.2 2000/07/13 11:33:45 michael
  544. + removed logs
  545. }