sstrings.inc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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, maxPrevValue, maxNewValue: 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. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  340. if (base = 10) then
  341. maxNewValue := MaxSIntValue + ord(negative)
  342. else
  343. maxNewValue := MaxUIntValue;
  344. while Code<=Length(s) do
  345. begin
  346. case s[Code] of
  347. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  348. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  349. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  350. else
  351. u:=16;
  352. end;
  353. Prev := Temp;
  354. Temp := Temp*ValUInt(base);
  355. If (u >= base) or
  356. (ValUInt(maxNewValue-u) < Temp) or
  357. (prev > maxPrevValue) Then
  358. Begin
  359. fpc_Val_SInt_ShortStr := 0;
  360. Exit
  361. End;
  362. Temp:=Temp+u;
  363. inc(code);
  364. end;
  365. code := 0;
  366. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  367. If Negative Then
  368. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  369. If Not(Negative) and (base <> 10) Then
  370. {sign extend the result to allow proper range checking}
  371. Case DestSize of
  372. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  373. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  374. { Uncomment the folling once full 64bit support is in place
  375. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);}
  376. End;
  377. end;
  378. {$ifdef hascompilerproc}
  379. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  380. { we have to pass the DestSize parameter on (JM) }
  381. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  382. {$endif hascompilerproc}
  383. Function fpc_Val_UInt_Shortstr(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  384. var
  385. u, prev : ValUInt;
  386. base : byte;
  387. negative : boolean;
  388. begin
  389. fpc_Val_UInt_Shortstr:=0;
  390. Code:=InitVal(s,negative,base);
  391. If Negative or (Code>length(s)) Then
  392. Exit;
  393. while Code<=Length(s) do
  394. begin
  395. case s[Code] of
  396. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  397. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  398. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  399. else
  400. u:=16;
  401. end;
  402. prev := fpc_Val_UInt_Shortstr;
  403. If (u>=base) or
  404. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  405. begin
  406. fpc_Val_UInt_Shortstr:=0;
  407. exit;
  408. end;
  409. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  410. inc(code);
  411. end;
  412. code := 0;
  413. end;
  414. Function fpc_Val_Real_ShortStr(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  415. var
  416. hd,
  417. esign,sign : valreal;
  418. exponent,i : longint;
  419. flags : byte;
  420. begin
  421. fpc_Val_Real_ShortStr:=0.0;
  422. code:=1;
  423. exponent:=0;
  424. esign:=1;
  425. flags:=0;
  426. sign:=1;
  427. while (code<=length(s)) and (s[code] in [' ',#9]) do
  428. inc(code);
  429. case s[code] of
  430. '+' : inc(code);
  431. '-' : begin
  432. sign:=-1;
  433. inc(code);
  434. end;
  435. end;
  436. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  437. begin
  438. { Read integer part }
  439. flags:=flags or 1;
  440. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  441. inc(code);
  442. end;
  443. { Decimal ? }
  444. if (s[code]='.') and (length(s)>=code) then
  445. begin
  446. hd:=1.0;
  447. inc(code);
  448. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  449. begin
  450. { Read fractional part. }
  451. flags:=flags or 2;
  452. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  453. hd:=hd*10.0;
  454. inc(code);
  455. end;
  456. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  457. end;
  458. { Again, read integer and fractional part}
  459. if flags=0 then
  460. begin
  461. fpc_Val_Real_ShortStr:=0.0;
  462. exit;
  463. end;
  464. { Exponent ? }
  465. if (upcase(s[code])='E') and (length(s)>=code) then
  466. begin
  467. inc(code);
  468. if s[code]='+' then
  469. inc(code)
  470. else
  471. if s[code]='-' then
  472. begin
  473. esign:=-1;
  474. inc(code);
  475. end;
  476. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  477. begin
  478. fpc_Val_Real_ShortStr:=0.0;
  479. exit;
  480. end;
  481. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  482. begin
  483. exponent:=exponent*10;
  484. exponent:=exponent+ord(s[code])-ord('0');
  485. inc(code);
  486. end;
  487. end;
  488. { Calculate Exponent }
  489. {
  490. if esign>0 then
  491. for i:=1 to exponent do
  492. fpc_Val_Real_ShortStr:=Val_Real_ShortStr*10
  493. else
  494. for i:=1 to exponent do
  495. fpc_Val_Real_ShortStr:=Val_Real_ShortStr/10; }
  496. hd:=1.0;
  497. for i:=1 to exponent do
  498. hd:=hd*10.0;
  499. if esign>0 then
  500. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  501. else
  502. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  503. { Not all characters are read ? }
  504. if length(s)>=code then
  505. begin
  506. fpc_Val_Real_ShortStr:=0.0;
  507. exit;
  508. end;
  509. { evaluate sign }
  510. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  511. { success ! }
  512. code:=0;
  513. end;
  514. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  515. begin
  516. Move (Buf[0],S[1],Len);
  517. S[0]:=chr(len);
  518. end;
  519. {
  520. $Log$
  521. Revision 1.17 2001-11-16 15:09:47 jonas
  522. * optimized fpc_val_sint_shortstr
  523. Revision 1.16 2001/08/13 12:40:16 jonas
  524. * renamed some str(x,y) and val(x,y) helpers so the naming scheme is the
  525. same for all string types
  526. + added the str(x,y) and val(x,y,z) helpers for int64/qword to
  527. compproc.inc
  528. Revision 1.15 2001/08/01 15:00:10 jonas
  529. + "compproc" helpers
  530. * renamed several helpers so that their name is the same as their
  531. "public alias", which should facilitate the conversion of processor
  532. specific code in the code generator to processor independent code
  533. * some small fixes to the val_ansistring and val_widestring helpers
  534. (always immediately exit if the source string is longer than 255
  535. chars)
  536. * fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
  537. still nil (used to crash, now return resp -1 and 0)
  538. Revision 1.14 2001/07/08 21:00:18 peter
  539. * various widestring updates, it works now mostly without charset
  540. mapping supported
  541. Revision 1.13 2001/07/04 12:02:14 jonas
  542. * fixed bug in ValSignedInt (it accepted some values slightly larger than
  543. high(cardinal) such as 4294967297) (merged)
  544. Revision 1.12 2001/06/04 11:43:51 peter
  545. * Formal const to var fixes
  546. * Hexstr(int64) added
  547. Revision 1.11 2001/04/13 22:30:04 peter
  548. * remove warnings
  549. Revision 1.10 2001/04/13 18:06:28 peter
  550. * removed rtllite define
  551. Revision 1.9 2001/03/03 12:38:53 jonas
  552. * made val for longints a bit faster
  553. Revision 1.8 2000/12/09 20:52:41 florian
  554. * val for dword and qword didn't handle the max values
  555. correctly
  556. * val for qword works again
  557. + val with int64/qword and ansistring implemented
  558. Revision 1.7 2000/11/23 11:41:56 jonas
  559. * fix for web bug 1265 by Peter (merged)
  560. Revision 1.6 2000/11/17 17:01:23 jonas
  561. * fixed bug for val when processing -2147483648 and low(int64) (merged)
  562. Revision 1.5 2000/11/06 20:34:24 peter
  563. * changed ver1_0 defines to temporary defs
  564. Revision 1.4 2000/10/21 18:20:17 florian
  565. * a lot of small changes:
  566. - setlength is internal
  567. - win32 graph unit extended
  568. ....
  569. Revision 1.3 2000/07/28 12:29:49 jonas
  570. * fixed web bug1069
  571. * fixed similar (and other) problems in val() for int64 and qword
  572. (both merged from fixes branch)
  573. Revision 1.2 2000/07/13 11:33:45 michael
  574. + removed logs
  575. }