sstrings.inc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  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 fpc_Shortstr_SetLength(var s:shortstring;len:StrLenInt);[Public,Alias : 'FPC_SHORTSTR_SETLENGTH']; {$ifdef hascompilerproc} compilerproc; {$endif}
  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,MaxLen : StrLenInt;
  100. pc : pchar;
  101. begin
  102. Pos:=0;
  103. if Length(SubStr)>0 then
  104. begin
  105. MaxLen:=Length(s)-Length(SubStr);
  106. i:=0;
  107. pc:=@s[1];
  108. while (i<=MaxLen) do
  109. begin
  110. inc(i);
  111. if (SubStr[1]=pc^) and
  112. (CompareChar(Substr[1],pc^,Length(SubStr))=0) then
  113. begin
  114. Pos:=i;
  115. exit;
  116. end;
  117. inc(pc);
  118. end;
  119. end;
  120. end;
  121. {Faster when looking for a single char...}
  122. function pos(c:char;const s:shortstring):StrLenInt;
  123. var
  124. i : StrLenInt;
  125. pc : pchar;
  126. begin
  127. pc:=@s[1];
  128. for i:=1 to length(s) do
  129. begin
  130. if pc^=c then
  131. begin
  132. pos:=i;
  133. exit;
  134. end;
  135. inc(pc);
  136. end;
  137. pos:=0;
  138. end;
  139. function copy(c:char;index : StrLenInt;count : StrLenInt): shortstring;
  140. begin
  141. if (index=1) and (Count>0) then
  142. Copy:=c
  143. else
  144. Copy:='';
  145. end;
  146. function pos(const substr : shortstring;c:char): StrLenInt;
  147. begin
  148. if (length(substr)=1) and (substr[1]=c) then
  149. Pos:=1
  150. else
  151. Pos:=0;
  152. end;
  153. {$ifdef IBM_CHAR_SET}
  154. const
  155. UpCaseTbl : shortstring[7]=#154#142#153#144#128#143#165;
  156. LoCaseTbl : shortstring[7]=#129#132#148#130#135#134#164;
  157. {$endif}
  158. function upcase(c : char) : char;
  159. {$IFDEF IBM_CHAR_SET}
  160. var
  161. i : longint;
  162. {$ENDIF}
  163. begin
  164. if (c in ['a'..'z']) then
  165. upcase:=char(byte(c)-32)
  166. else
  167. {$IFDEF IBM_CHAR_SET}
  168. begin
  169. i:=Pos(c,LoCaseTbl);
  170. if i>0 then
  171. upcase:=UpCaseTbl[i]
  172. else
  173. upcase:=c;
  174. end;
  175. {$ELSE}
  176. upcase:=c;
  177. {$ENDIF}
  178. end;
  179. function upcase(const s : shortstring) : shortstring;
  180. var
  181. i : longint;
  182. begin
  183. upcase[0]:=s[0];
  184. for i := 1 to length (s) do
  185. upcase[i] := upcase (s[i]);
  186. end;
  187. function lowercase(c : char) : char;
  188. {$IFDEF IBM_CHAR_SET}
  189. var
  190. i : longint;
  191. {$ENDIF}
  192. begin
  193. if (c in ['A'..'Z']) then
  194. lowercase:=char(byte(c)+32)
  195. else
  196. {$IFDEF IBM_CHAR_SET}
  197. begin
  198. i:=Pos(c,UpCaseTbl);
  199. if i>0 then
  200. lowercase:=LoCaseTbl[i]
  201. else
  202. lowercase:=c;
  203. end;
  204. {$ELSE}
  205. lowercase:=c;
  206. {$ENDIF}
  207. end;
  208. function lowercase(const s : shortstring) : shortstring;
  209. var
  210. i : longint;
  211. begin
  212. lowercase [0]:=s[0];
  213. for i:=1 to length(s) do
  214. lowercase[i]:=lowercase (s[i]);
  215. end;
  216. const
  217. HexTbl : array[0..15] of char='0123456789ABCDEF';
  218. function hexstr(val : longint;cnt : byte) : shortstring;
  219. var
  220. i : longint;
  221. begin
  222. hexstr[0]:=char(cnt);
  223. for i:=cnt downto 1 do
  224. begin
  225. hexstr[i]:=hextbl[val and $f];
  226. val:=val shr 4;
  227. end;
  228. end;
  229. function binstr(val : longint;cnt : byte) : shortstring;
  230. var
  231. i : longint;
  232. begin
  233. binstr[0]:=char(cnt);
  234. for i:=cnt downto 1 do
  235. begin
  236. binstr[i]:=char(48+val and 1);
  237. val:=val shr 1;
  238. end;
  239. end;
  240. function hexstr(val : int64;cnt : byte) : shortstring;
  241. var
  242. i : longint;
  243. begin
  244. hexstr[0]:=char(cnt);
  245. for i:=cnt downto 1 do
  246. begin
  247. hexstr[i]:=hextbl[val and $f];
  248. val:=val shr 4;
  249. end;
  250. end;
  251. function binstr(val : int64;cnt : byte) : shortstring;
  252. var
  253. i : longint;
  254. begin
  255. binstr[0]:=char(cnt);
  256. for i:=cnt downto 1 do
  257. begin
  258. binstr[i]:=char(48+val and 1);
  259. val:=val shr 1;
  260. end;
  261. end;
  262. function space (b : byte): shortstring;
  263. begin
  264. space[0] := chr(b);
  265. FillChar (Space[1],b,' ');
  266. end;
  267. {*****************************************************************************
  268. Str() Helpers
  269. *****************************************************************************}
  270. procedure fpc_ShortStr_Float(d : ValReal;len,fr,rt : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; {$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  271. begin
  272. str_real(len,fr,d,treal_type(rt),s);
  273. end;
  274. procedure fpc_shortstr_longint(v : longint;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  275. begin
  276. int_str(v,s);
  277. if length(s)<len then
  278. s:=space(len-length(s))+s;
  279. end;
  280. procedure fpc_shortstr_cardinal(v : cardinal;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_CARDINAL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  281. begin
  282. int_str(v,s);
  283. if length(s)<len then
  284. s:=space(len-length(s))+s;
  285. end;
  286. {*****************************************************************************
  287. Val() Functions
  288. *****************************************************************************}
  289. Function InitVal(const s:shortstring;var negativ:boolean;var base:byte):ValSInt;
  290. var
  291. Code : Longint;
  292. begin
  293. {Skip Spaces and Tab}
  294. code:=1;
  295. while (code<=length(s)) and (s[code] in [' ',#9]) do
  296. inc(code);
  297. {Sign}
  298. negativ:=false;
  299. case s[code] of
  300. '-' : begin
  301. negativ:=true;
  302. inc(code);
  303. end;
  304. '+' : inc(code);
  305. end;
  306. {Base}
  307. base:=10;
  308. if code<=length(s) then
  309. begin
  310. case s[code] of
  311. '$' : begin
  312. base:=16;
  313. repeat
  314. inc(code);
  315. until (code>=length(s)) or (s[code]<>'0');
  316. end;
  317. '%' : begin
  318. base:=2;
  319. inc(code);
  320. end;
  321. end;
  322. end;
  323. InitVal:=code;
  324. end;
  325. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  326. var
  327. u, temp, prev, maxValue: ValUInt;
  328. base : byte;
  329. negative : boolean;
  330. begin
  331. fpc_Val_SInt_ShortStr := 0;
  332. Temp:=0;
  333. Code:=InitVal(s,negative,base);
  334. if Code>length(s) then
  335. exit;
  336. maxValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  337. while Code<=Length(s) do
  338. begin
  339. case s[Code] of
  340. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  341. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  342. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  343. else
  344. u:=16;
  345. end;
  346. Prev := Temp;
  347. Temp := Temp*ValUInt(base);
  348. If (u >= base) or
  349. ((base = 10) and
  350. (ValUInt(MaxSIntValue-u+ord(negative)) < Temp)) or
  351. ((base <> 10) and
  352. (ValUInt(MaxUIntValue-Temp) < u)) or
  353. (prev > maxValue) Then
  354. Begin
  355. fpc_Val_SInt_ShortStr := 0;
  356. Exit
  357. End;
  358. Temp:=Temp+u;
  359. inc(code);
  360. end;
  361. code := 0;
  362. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  363. If Negative Then
  364. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  365. If Not(Negative) and (base <> 10) Then
  366. {sign extend the result to allow proper range checking}
  367. Case DestSize of
  368. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  369. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  370. { Uncomment the folling once full 64bit support is in place
  371. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);}
  372. End;
  373. end;
  374. {$ifdef hascompilerproc}
  375. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  376. { we have to pass the DestSize parameter on (JM) }
  377. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  378. {$endif hascompilerproc}
  379. Function fpc_Val_UInt_Shortstr(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  380. var
  381. u, prev : ValUInt;
  382. base : byte;
  383. negative : boolean;
  384. begin
  385. fpc_Val_UInt_Shortstr:=0;
  386. Code:=InitVal(s,negative,base);
  387. If Negative or (Code>length(s)) Then
  388. Exit;
  389. while Code<=Length(s) do
  390. begin
  391. case s[Code] of
  392. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  393. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  394. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  395. else
  396. u:=16;
  397. end;
  398. prev := fpc_Val_UInt_Shortstr;
  399. If (u>=base) or
  400. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  401. begin
  402. fpc_Val_UInt_Shortstr:=0;
  403. exit;
  404. end;
  405. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  406. inc(code);
  407. end;
  408. code := 0;
  409. end;
  410. Function fpc_Val_Real_ShortStr(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  411. var
  412. hd,
  413. esign,sign : valreal;
  414. exponent,i : longint;
  415. flags : byte;
  416. begin
  417. fpc_Val_Real_ShortStr:=0.0;
  418. code:=1;
  419. exponent:=0;
  420. esign:=1;
  421. flags:=0;
  422. sign:=1;
  423. while (code<=length(s)) and (s[code] in [' ',#9]) do
  424. inc(code);
  425. case s[code] of
  426. '+' : inc(code);
  427. '-' : begin
  428. sign:=-1;
  429. inc(code);
  430. end;
  431. end;
  432. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  433. begin
  434. { Read integer part }
  435. flags:=flags or 1;
  436. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  437. inc(code);
  438. end;
  439. { Decimal ? }
  440. if (s[code]='.') and (length(s)>=code) then
  441. begin
  442. hd:=1.0;
  443. inc(code);
  444. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  445. begin
  446. { Read fractional part. }
  447. flags:=flags or 2;
  448. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  449. hd:=hd*10.0;
  450. inc(code);
  451. end;
  452. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  453. end;
  454. { Again, read integer and fractional part}
  455. if flags=0 then
  456. begin
  457. fpc_Val_Real_ShortStr:=0.0;
  458. exit;
  459. end;
  460. { Exponent ? }
  461. if (upcase(s[code])='E') and (length(s)>=code) then
  462. begin
  463. inc(code);
  464. if s[code]='+' then
  465. inc(code)
  466. else
  467. if s[code]='-' then
  468. begin
  469. esign:=-1;
  470. inc(code);
  471. end;
  472. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  473. begin
  474. fpc_Val_Real_ShortStr:=0.0;
  475. exit;
  476. end;
  477. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  478. begin
  479. exponent:=exponent*10;
  480. exponent:=exponent+ord(s[code])-ord('0');
  481. inc(code);
  482. end;
  483. end;
  484. { Calculate Exponent }
  485. {
  486. if esign>0 then
  487. for i:=1 to exponent do
  488. fpc_Val_Real_ShortStr:=Val_Real_ShortStr*10
  489. else
  490. for i:=1 to exponent do
  491. fpc_Val_Real_ShortStr:=Val_Real_ShortStr/10; }
  492. hd:=1.0;
  493. for i:=1 to exponent do
  494. hd:=hd*10.0;
  495. if esign>0 then
  496. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  497. else
  498. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  499. { Not all characters are read ? }
  500. if length(s)>=code then
  501. begin
  502. fpc_Val_Real_ShortStr:=0.0;
  503. exit;
  504. end;
  505. { evaluate sign }
  506. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  507. { success ! }
  508. code:=0;
  509. end;
  510. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  511. begin
  512. Move (Buf[0],S[1],Len);
  513. S[0]:=chr(len);
  514. end;
  515. {
  516. $Log$
  517. Revision 1.15 2001-08-01 15:00:10 jonas
  518. + "compproc" helpers
  519. * renamed several helpers so that their name is the same as their
  520. "public alias", which should facilitate the conversion of processor
  521. specific code in the code generator to processor independent code
  522. * some small fixes to the val_ansistring and val_widestring helpers
  523. (always immediately exit if the source string is longer than 255
  524. chars)
  525. * fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
  526. still nil (used to crash, now return resp -1 and 0)
  527. Revision 1.14 2001/07/08 21:00:18 peter
  528. * various widestring updates, it works now mostly without charset
  529. mapping supported
  530. Revision 1.13 2001/07/04 12:02:14 jonas
  531. * fixed bug in ValSignedInt (it accepted some values slightly larger than
  532. high(cardinal) such as 4294967297) (merged)
  533. Revision 1.12 2001/06/04 11:43:51 peter
  534. * Formal const to var fixes
  535. * Hexstr(int64) added
  536. Revision 1.11 2001/04/13 22:30:04 peter
  537. * remove warnings
  538. Revision 1.10 2001/04/13 18:06:28 peter
  539. * removed rtllite define
  540. Revision 1.9 2001/03/03 12:38:53 jonas
  541. * made val for longints a bit faster
  542. Revision 1.8 2000/12/09 20:52:41 florian
  543. * val for dword and qword didn't handle the max values
  544. correctly
  545. * val for qword works again
  546. + val with int64/qword and ansistring implemented
  547. Revision 1.7 2000/11/23 11:41:56 jonas
  548. * fix for web bug 1265 by Peter (merged)
  549. Revision 1.6 2000/11/17 17:01:23 jonas
  550. * fixed bug for val when processing -2147483648 and low(int64) (merged)
  551. Revision 1.5 2000/11/06 20:34:24 peter
  552. * changed ver1_0 defines to temporary defs
  553. Revision 1.4 2000/10/21 18:20:17 florian
  554. * a lot of small changes:
  555. - setlength is internal
  556. - win32 graph unit extended
  557. ....
  558. Revision 1.3 2000/07/28 12:29:49 jonas
  559. * fixed web bug1069
  560. * fixed similar (and other) problems in val() for int64 and qword
  561. (both merged from fixes branch)
  562. Revision 1.2 2000/07/13 11:33:45 michael
  563. + removed logs
  564. }