sstrings.inc 13 KB

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