sstrings.inc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  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;overload;
  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; overload;
  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 octstr(val : longint;cnt : byte) : shortstring;
  229. var
  230. i : longint;
  231. begin
  232. octstr[0]:=char(cnt);
  233. for i:=cnt downto 1 do
  234. begin
  235. octstr[i]:=hextbl[val and 7];
  236. val:=val shr 3;
  237. end;
  238. end;
  239. function binstr(val : longint;cnt : byte) : shortstring;
  240. var
  241. i : longint;
  242. begin
  243. binstr[0]:=char(cnt);
  244. for i:=cnt downto 1 do
  245. begin
  246. binstr[i]:=char(48+val and 1);
  247. val:=val shr 1;
  248. end;
  249. end;
  250. function hexstr(val : int64;cnt : byte) : shortstring;
  251. var
  252. i : longint;
  253. begin
  254. hexstr[0]:=char(cnt);
  255. for i:=cnt downto 1 do
  256. begin
  257. hexstr[i]:=hextbl[val and $f];
  258. val:=val shr 4;
  259. end;
  260. end;
  261. function octstr(val : int64;cnt : byte) : shortstring;
  262. var
  263. i : longint;
  264. begin
  265. octstr[0]:=char(cnt);
  266. for i:=cnt downto 1 do
  267. begin
  268. octstr[i]:=hextbl[val and 7];
  269. val:=val shr 3;
  270. end;
  271. end;
  272. function binstr(val : int64;cnt : byte) : shortstring;
  273. var
  274. i : longint;
  275. begin
  276. binstr[0]:=char(cnt);
  277. for i:=cnt downto 1 do
  278. begin
  279. binstr[i]:=char(48+val and 1);
  280. val:=val shr 1;
  281. end;
  282. end;
  283. function space (b : byte): shortstring;
  284. begin
  285. space[0] := chr(b);
  286. FillChar (Space[1],b,' ');
  287. end;
  288. {*****************************************************************************
  289. Str() Helpers
  290. *****************************************************************************}
  291. procedure fpc_shortstr_longint(v : longint;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_LONGINT']; {$ifdef hascompilerproc} compilerproc; {$endif}
  292. begin
  293. int_str(v,s);
  294. if length(s)<len then
  295. s:=space(len-length(s))+s;
  296. end;
  297. procedure fpc_shortstr_cardinal(v : cardinal;len : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_CARDINAL']; {$ifdef hascompilerproc} compilerproc; {$endif}
  298. begin
  299. int_str(v,s);
  300. if length(s)<len then
  301. s:=space(len-length(s))+s;
  302. end;
  303. { fpc_shortstr_longint must appear before this file is included, because }
  304. { it's used inside real2str.inc and otherwise the searching via the }
  305. { compilerproc name will fail (JM) }
  306. {$I real2str.inc}
  307. procedure fpc_ShortStr_Float(d : ValReal;len,fr,rt : longint;var s : shortstring);[public,alias:'FPC_SHORTSTR_FLOAT']; {$ifdef hascompilerproc}compilerproc;{$endif hascompilerproc}
  308. begin
  309. str_real(len,fr,d,treal_type(rt),s);
  310. end;
  311. {*****************************************************************************
  312. Val() Functions
  313. *****************************************************************************}
  314. Function InitVal(const s:shortstring;var negativ:boolean;var base:byte):ValSInt;
  315. var
  316. Code : Longint;
  317. begin
  318. {Skip Spaces and Tab}
  319. code:=1;
  320. while (code<=length(s)) and (s[code] in [' ',#9]) do
  321. inc(code);
  322. {Sign}
  323. negativ:=false;
  324. case s[code] of
  325. '-' : begin
  326. negativ:=true;
  327. inc(code);
  328. end;
  329. '+' : inc(code);
  330. end;
  331. {Base}
  332. base:=10;
  333. if code<=length(s) then
  334. begin
  335. case s[code] of
  336. '$' : begin
  337. base:=16;
  338. repeat
  339. inc(code);
  340. until (code>=length(s)) or (s[code]<>'0');
  341. end;
  342. '%' : begin
  343. base:=2;
  344. inc(code);
  345. end;
  346. '&' : begin
  347. Base:=8;
  348. repeat
  349. inc(code);
  350. until (code>=length(s)) or (s[code]<>'0');
  351. end;
  352. end;
  353. end;
  354. InitVal:=code;
  355. end;
  356. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  357. var
  358. u, temp, prev, maxPrevValue, maxNewValue: ValUInt;
  359. base : byte;
  360. negative : boolean;
  361. begin
  362. fpc_Val_SInt_ShortStr := 0;
  363. Temp:=0;
  364. Code:=InitVal(s,negative,base);
  365. if Code>length(s) then
  366. exit;
  367. maxPrevValue := ValUInt(MaxUIntValue) div ValUInt(Base);
  368. if (base = 10) then
  369. maxNewValue := MaxSIntValue + ord(negative)
  370. else
  371. maxNewValue := MaxUIntValue;
  372. while Code<=Length(s) do
  373. begin
  374. case s[Code] of
  375. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  376. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  377. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  378. else
  379. u:=16;
  380. end;
  381. Prev := Temp;
  382. Temp := Temp*ValUInt(base);
  383. If (u >= base) or
  384. (ValUInt(maxNewValue-u) < Temp) or
  385. (prev > maxPrevValue) Then
  386. Begin
  387. fpc_Val_SInt_ShortStr := 0;
  388. Exit
  389. End;
  390. Temp:=Temp+u;
  391. inc(code);
  392. end;
  393. code := 0;
  394. fpc_Val_SInt_ShortStr := ValSInt(Temp);
  395. If Negative Then
  396. fpc_Val_SInt_ShortStr := -fpc_Val_SInt_ShortStr;
  397. If Not(Negative) and (base <> 10) Then
  398. {sign extend the result to allow proper range checking}
  399. Case DestSize of
  400. 1: fpc_Val_SInt_ShortStr := shortint(fpc_Val_SInt_ShortStr);
  401. 2: fpc_Val_SInt_ShortStr := smallint(fpc_Val_SInt_ShortStr);
  402. { Uncomment the folling once full 64bit support is in place
  403. 4: fpc_Val_SInt_ShortStr := longint(fpc_Val_SInt_ShortStr);}
  404. End;
  405. end;
  406. {$ifdef hascompilerproc}
  407. { we need this for fpc_Val_SInt_Ansistr and fpc_Val_SInt_WideStr because }
  408. { we have to pass the DestSize parameter on (JM) }
  409. Function fpc_Val_SInt_ShortStr(DestSize: longint; Const S: ShortString; var Code: ValSInt): ValSInt; [external name 'FPC_VAL_SINT_SHORTSTR'];
  410. {$endif hascompilerproc}
  411. Function fpc_Val_UInt_Shortstr(Const S: ShortString; var Code: ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  412. var
  413. u, prev : ValUInt;
  414. base : byte;
  415. negative : boolean;
  416. begin
  417. fpc_Val_UInt_Shortstr:=0;
  418. Code:=InitVal(s,negative,base);
  419. If Negative or (Code>length(s)) Then
  420. Exit;
  421. while Code<=Length(s) do
  422. begin
  423. case s[Code] of
  424. '0'..'9' : u:=Ord(S[Code])-Ord('0');
  425. 'A'..'F' : u:=Ord(S[Code])-(Ord('A')-10);
  426. 'a'..'f' : u:=Ord(S[Code])-(Ord('a')-10);
  427. else
  428. u:=16;
  429. end;
  430. prev := fpc_Val_UInt_Shortstr;
  431. If (u>=base) or
  432. (ValUInt(MaxUIntValue-u) div ValUInt(Base)<prev) then
  433. begin
  434. fpc_Val_UInt_Shortstr:=0;
  435. exit;
  436. end;
  437. fpc_Val_UInt_Shortstr:=fpc_Val_UInt_Shortstr*ValUInt(base) + u;
  438. inc(code);
  439. end;
  440. code := 0;
  441. end;
  442. Function fpc_Val_Real_ShortStr(const s : shortstring; var code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_SHORTSTR']; {$ifdef hascompilerproc} compilerproc; {$endif}
  443. var
  444. hd,
  445. esign,sign : valreal;
  446. exponent,i : longint;
  447. flags : byte;
  448. begin
  449. fpc_Val_Real_ShortStr:=0.0;
  450. code:=1;
  451. exponent:=0;
  452. esign:=1;
  453. flags:=0;
  454. sign:=1;
  455. while (code<=length(s)) and (s[code] in [' ',#9]) do
  456. inc(code);
  457. case s[code] of
  458. '+' : inc(code);
  459. '-' : begin
  460. sign:=-1;
  461. inc(code);
  462. end;
  463. end;
  464. while (Code<=Length(s)) and (s[code] in ['0'..'9']) do
  465. begin
  466. { Read integer part }
  467. flags:=flags or 1;
  468. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  469. inc(code);
  470. end;
  471. { Decimal ? }
  472. if (s[code]='.') and (length(s)>=code) then
  473. begin
  474. hd:=1.0;
  475. inc(code);
  476. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  477. begin
  478. { Read fractional part. }
  479. flags:=flags or 2;
  480. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*10+(ord(s[code])-ord('0'));
  481. hd:=hd*10.0;
  482. inc(code);
  483. end;
  484. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  485. end;
  486. { Again, read integer and fractional part}
  487. if flags=0 then
  488. begin
  489. fpc_Val_Real_ShortStr:=0.0;
  490. exit;
  491. end;
  492. { Exponent ? }
  493. if (upcase(s[code])='E') and (length(s)>=code) then
  494. begin
  495. inc(code);
  496. if s[code]='+' then
  497. inc(code)
  498. else
  499. if s[code]='-' then
  500. begin
  501. esign:=-1;
  502. inc(code);
  503. end;
  504. if not(s[code] in ['0'..'9']) or (length(s)<code) then
  505. begin
  506. fpc_Val_Real_ShortStr:=0.0;
  507. exit;
  508. end;
  509. while (s[code] in ['0'..'9']) and (length(s)>=code) do
  510. begin
  511. exponent:=exponent*10;
  512. exponent:=exponent+ord(s[code])-ord('0');
  513. inc(code);
  514. end;
  515. end;
  516. { Calculate Exponent }
  517. {
  518. if esign>0 then
  519. for i:=1 to exponent do
  520. fpc_Val_Real_ShortStr:=Val_Real_ShortStr*10
  521. else
  522. for i:=1 to exponent do
  523. fpc_Val_Real_ShortStr:=Val_Real_ShortStr/10; }
  524. hd:=1.0;
  525. for i:=1 to exponent do
  526. hd:=hd*10.0;
  527. if esign>0 then
  528. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*hd
  529. else
  530. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr/hd;
  531. { Not all characters are read ? }
  532. if length(s)>=code then
  533. begin
  534. fpc_Val_Real_ShortStr:=0.0;
  535. exit;
  536. end;
  537. { evaluate sign }
  538. fpc_Val_Real_ShortStr:=fpc_Val_Real_ShortStr*sign;
  539. { success ! }
  540. code:=0;
  541. end;
  542. Procedure SetString (Var S : Shortstring; Buf : PChar; Len : Longint);
  543. begin
  544. Move (Buf[0],S[1],Len);
  545. S[0]:=chr(len);
  546. end;
  547. {
  548. $Log$
  549. Revision 1.19 2002-08-06 20:53:38 michael
  550. + Added support for octal strings (using &)
  551. Revision 1.18 2002/01/24 18:27:06 peter
  552. * lowercase() overloaded
  553. Revision 1.17 2001/11/16 15:09:47 jonas
  554. * optimized fpc_val_sint_shortstr
  555. Revision 1.16 2001/08/13 12:40:16 jonas
  556. * renamed some str(x,y) and val(x,y) helpers so the naming scheme is the
  557. same for all string types
  558. + added the str(x,y) and val(x,y,z) helpers for int64/qword to
  559. compproc.inc
  560. Revision 1.15 2001/08/01 15:00:10 jonas
  561. + "compproc" helpers
  562. * renamed several helpers so that their name is the same as their
  563. "public alias", which should facilitate the conversion of processor
  564. specific code in the code generator to processor independent code
  565. * some small fixes to the val_ansistring and val_widestring helpers
  566. (always immediately exit if the source string is longer than 255
  567. chars)
  568. * fixed fpc_dynarray_high and fpc_dynarray_length if the dynarray is
  569. still nil (used to crash, now return resp -1 and 0)
  570. Revision 1.14 2001/07/08 21:00:18 peter
  571. * various widestring updates, it works now mostly without charset
  572. mapping supported
  573. Revision 1.13 2001/07/04 12:02:14 jonas
  574. * fixed bug in ValSignedInt (it accepted some values slightly larger than
  575. high(cardinal) such as 4294967297) (merged)
  576. Revision 1.12 2001/06/04 11:43:51 peter
  577. * Formal const to var fixes
  578. * Hexstr(int64) added
  579. Revision 1.11 2001/04/13 22:30:04 peter
  580. * remove warnings
  581. Revision 1.10 2001/04/13 18:06:28 peter
  582. * removed rtllite define
  583. Revision 1.9 2001/03/03 12:38:53 jonas
  584. * made val for longints a bit faster
  585. Revision 1.8 2000/12/09 20:52:41 florian
  586. * val for dword and qword didn't handle the max values
  587. correctly
  588. * val for qword works again
  589. + val with int64/qword and ansistring implemented
  590. Revision 1.7 2000/11/23 11:41:56 jonas
  591. * fix for web bug 1265 by Peter (merged)
  592. Revision 1.6 2000/11/17 17:01:23 jonas
  593. * fixed bug for val when processing -2147483648 and low(int64) (merged)
  594. Revision 1.5 2000/11/06 20:34:24 peter
  595. * changed ver1_0 defines to temporary defs
  596. Revision 1.4 2000/10/21 18:20:17 florian
  597. * a lot of small changes:
  598. - setlength is internal
  599. - win32 graph unit extended
  600. ....
  601. Revision 1.3 2000/07/28 12:29:49 jonas
  602. * fixed web bug1069
  603. * fixed similar (and other) problems in val() for int64 and qword
  604. (both merged from fixes branch)
  605. Revision 1.2 2000/07/13 11:33:45 michael
  606. + removed logs
  607. }