sstrings.inc 16 KB

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